mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-20 13:08:07 +00:00
Use account recovery token FlexiAPI endpoint
This commit is contained in:
parent
1fdc2bcc58
commit
61517461dd
9 changed files with 421 additions and 46 deletions
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.ui.assistant.fragment
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.net.toUri
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.R
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.GenericFragment
|
||||
import org.linphone.databinding.AssistantRecoverAccountFragmentBinding
|
||||
import org.linphone.ui.assistant.viewmodel.AccountCreationViewModel
|
||||
import kotlin.getValue
|
||||
|
||||
@UiThread
|
||||
class RecoverAccountFragment : GenericFragment() {
|
||||
companion object {
|
||||
private const val TAG = "[Recover Account Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: AssistantRecoverAccountFragmentBinding
|
||||
|
||||
private val viewModel: AccountCreationViewModel by navGraphViewModels(
|
||||
R.id.assistant_nav_graph
|
||||
)
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = AssistantRecoverAccountFragmentBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
binding.viewModel = viewModel
|
||||
observeToastEvents(viewModel)
|
||||
|
||||
viewModel.accountRecoveryTokenReceivedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { token ->
|
||||
Log.i("$TAG Account recovery token received [$token], opening browser")
|
||||
recoverPhoneNumberAccount(token)
|
||||
}
|
||||
}
|
||||
|
||||
binding.setBackClickListener {
|
||||
goBack()
|
||||
}
|
||||
|
||||
binding.setRecoverEmailAccountClickListener {
|
||||
recoverEmailAccount()
|
||||
}
|
||||
|
||||
binding.setRecoverPhoneNumberAccountClickListener {
|
||||
viewModel.requestAccountRecoveryToken()
|
||||
}
|
||||
}
|
||||
|
||||
private fun goBack() {
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
|
||||
private fun recoverEmailAccount() {
|
||||
val rootUrl = getString(R.string.web_platform_forgotten_password_url)
|
||||
val url = "$rootUrl/recovery/email"
|
||||
try {
|
||||
Log.i("$TAG Trying to open [$url] URL")
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, url.toUri())
|
||||
startActivity(browserIntent)
|
||||
} catch (ise: IllegalStateException) {
|
||||
Log.e(
|
||||
"$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise"
|
||||
)
|
||||
} catch (anfe: ActivityNotFoundException) {
|
||||
Log.e(
|
||||
"$TAG Can't start ACTION_VIEW intent for URL [$url], ActivityNotFoundException: $anfe"
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(
|
||||
"$TAG Can't start ACTION_VIEW intent for URL [$url]: $e"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun recoverPhoneNumberAccount(recoveryToken: String) {
|
||||
val rootUrl = getString(R.string.web_platform_forgotten_password_url)
|
||||
val url = "$rootUrl/recovery/phone/$recoveryToken"
|
||||
try {
|
||||
Log.i("$TAG Trying to open [$url] URL")
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, url.toUri())
|
||||
startActivity(browserIntent)
|
||||
} catch (ise: IllegalStateException) {
|
||||
Log.e(
|
||||
"$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise"
|
||||
)
|
||||
} catch (anfe: ActivityNotFoundException) {
|
||||
Log.e(
|
||||
"$TAG Can't start ACTION_VIEW intent for URL [$url], ActivityNotFoundException: $anfe"
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(
|
||||
"$TAG Can't start ACTION_VIEW intent for URL [$url]: $e"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,8 +111,11 @@ class LandingFragment : GenericFragment() {
|
|||
}
|
||||
|
||||
binding.setForgottenPasswordClickListener {
|
||||
val url = getString(R.string.web_platform_forgotten_password_url)
|
||||
openUrlInBrowser(url)
|
||||
if (findNavController().currentDestination?.id == R.id.landingFragment) {
|
||||
val action =
|
||||
LandingFragmentDirections.actionLandingFragmentToRecoverAccountFragment()
|
||||
findNavController().navigate(action)
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.showPassword.observe(viewLifecycleOwner) {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ import org.linphone.LinphoneApplication.Companion.coreContext
|
|||
import org.linphone.R
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.AssistantRegisterFragmentBinding
|
||||
import org.linphone.ui.GenericActivity
|
||||
import org.linphone.ui.GenericFragment
|
||||
import org.linphone.ui.assistant.viewmodel.AccountCreationViewModel
|
||||
import org.linphone.utils.ConfirmationDialogModel
|
||||
|
|
@ -164,15 +163,6 @@ class RegisterFragment : GenericFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
viewModel.errorHappenedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { error ->
|
||||
(requireActivity() as GenericActivity).showRedToast(
|
||||
error,
|
||||
R.drawable.warning_circle
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val telephonyManager = requireContext().getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
val countryIso = telephonyManager.networkCountryIso
|
||||
coreContext.postOnCoreThread {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ import org.linphone.core.Dictionary
|
|||
import org.linphone.core.Factory
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.GenericViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
|
|
@ -105,7 +104,7 @@ class AccountCreationViewModel
|
|||
|
||||
val accountCreatedEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
val errorHappenedEvent: MutableLiveData<Event<String>> by lazy {
|
||||
val accountRecoveryTokenReceivedEvent: MutableLiveData<Event<String>> by lazy {
|
||||
MutableLiveData<Event<String>>()
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +112,9 @@ class AccountCreationViewModel
|
|||
private var waitForPushJob: Job? = null
|
||||
|
||||
private lateinit var accountManagerServices: AccountManagerServices
|
||||
private var requestedTokenIsForAccountCreation: Boolean = true
|
||||
private var accountCreationToken: String? = null
|
||||
private var accountRecoveryToken: String? = null
|
||||
|
||||
private var accountCreatedAuthInfo: AuthInfo? = null
|
||||
private var accountCreated: Account? = null
|
||||
|
|
@ -124,7 +125,7 @@ class AccountCreationViewModel
|
|||
request: AccountManagerServicesRequest,
|
||||
data: String?
|
||||
) {
|
||||
Log.i("$TAG Request [$request] was successful, data is [$data]")
|
||||
Log.i("$TAG Request [${request.type}] was successful, data is [$data]")
|
||||
operationInProgress.postValue(false)
|
||||
|
||||
when (request.type) {
|
||||
|
|
@ -138,6 +139,10 @@ class AccountCreationViewModel
|
|||
)
|
||||
}
|
||||
}
|
||||
AccountManagerServicesRequest.Type.SendAccountCreationTokenByPush,
|
||||
AccountManagerServicesRequest.Type.SendAccountRecoveryTokenByPush -> {
|
||||
Log.i("$TAG Send token by push notification request has been accepted, it should be received soon")
|
||||
}
|
||||
AccountManagerServicesRequest.Type.SendPhoneNumberLinkingCodeBySms -> {
|
||||
goToSmsCodeConfirmationViewEvent.postValue(Event(true))
|
||||
}
|
||||
|
|
@ -156,7 +161,7 @@ class AccountCreationViewModel
|
|||
parameterErrors: Dictionary?
|
||||
) {
|
||||
Log.e(
|
||||
"$TAG Request [$request] returned an error with status code [$statusCode] and message [$errorMessage]"
|
||||
"$TAG Request [${request.type}] returned an error with status code [$statusCode] and message [$errorMessage]"
|
||||
)
|
||||
operationInProgress.postValue(false)
|
||||
|
||||
|
|
@ -174,7 +179,8 @@ class AccountCreationViewModel
|
|||
}
|
||||
|
||||
when (request.type) {
|
||||
AccountManagerServicesRequest.Type.SendAccountCreationTokenByPush -> {
|
||||
AccountManagerServicesRequest.Type.SendAccountCreationTokenByPush,
|
||||
AccountManagerServicesRequest.Type.SendAccountRecoveryTokenByPush -> {
|
||||
Log.w("$TAG Cancelling job waiting for push notification")
|
||||
waitingForFlexiApiPushToken = false
|
||||
waitForPushJob?.cancel()
|
||||
|
|
@ -220,11 +226,19 @@ class AccountCreationViewModel
|
|||
|
||||
val token = customPayload.getString("token")
|
||||
if (token.isNotEmpty()) {
|
||||
accountCreationToken = token
|
||||
Log.i(
|
||||
"$TAG Extracted token [$accountCreationToken] from push payload, creating account"
|
||||
)
|
||||
createAccount()
|
||||
if (requestedTokenIsForAccountCreation) {
|
||||
accountCreationToken = token
|
||||
Log.i(
|
||||
"$TAG Extracted token [$accountCreationToken] from push payload, creating account"
|
||||
)
|
||||
createAccount()
|
||||
} else {
|
||||
accountRecoveryToken = token
|
||||
Log.i(
|
||||
"$TAG Extracted token [$accountRecoveryToken] from push payload, opening browser"
|
||||
)
|
||||
accountRecoveryTokenReceivedEvent.postValue(Event(token))
|
||||
}
|
||||
} else {
|
||||
Log.e("$TAG Push payload JSON object has an empty 'token'!")
|
||||
onFlexiApiTokenRequestError()
|
||||
|
|
@ -317,9 +331,7 @@ class AccountCreationViewModel
|
|||
normalizedPhoneNumberEvent.postValue(Event(formattedPhoneNumber))
|
||||
} else {
|
||||
Log.e("$TAG Account manager services hasn't been initialized!")
|
||||
errorHappenedEvent.postValue(
|
||||
Event(AppUtils.getString(R.string.assistant_account_register_unexpected_error))
|
||||
)
|
||||
showRedToast(R.string.assistant_account_register_unexpected_error, R.drawable.warning_circle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -330,8 +342,8 @@ class AccountCreationViewModel
|
|||
|
||||
coreContext.postOnCoreThread {
|
||||
if (accountCreationToken.isNullOrEmpty()) {
|
||||
Log.i("$TAG We don't have a creation token, let's request one")
|
||||
requestFlexiApiToken()
|
||||
Log.i("$TAG We don't have an account creation token yet, let's request one")
|
||||
requestFlexiApiToken(requestAccountCreationToken = true)
|
||||
} else {
|
||||
val authInfo = accountCreatedAuthInfo
|
||||
if (authInfo != null) {
|
||||
|
|
@ -345,6 +357,20 @@ class AccountCreationViewModel
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun requestAccountRecoveryToken() {
|
||||
coreContext.postOnCoreThread {
|
||||
val existingToken = accountRecoveryToken
|
||||
if (existingToken.isNullOrEmpty()) {
|
||||
Log.i("$TAG We don't have an account recovery token yet, let's request one")
|
||||
requestFlexiApiToken(requestAccountCreationToken = false)
|
||||
} else {
|
||||
Log.i("$TAG We've already have a token [$existingToken], using it")
|
||||
accountRecoveryTokenReceivedEvent.postValue(Event(existingToken))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleShowPassword() {
|
||||
showPassword.value = showPassword.value == false
|
||||
|
|
@ -365,7 +391,7 @@ class AccountCreationViewModel
|
|||
val account = accountCreated
|
||||
if (::accountManagerServices.isInitialized && account != null) {
|
||||
val code =
|
||||
"${smsCodeFirstDigit.value}${smsCodeSecondDigit.value}${smsCodeThirdDigit.value}${smsCodeLastDigit.value}"
|
||||
"${smsCodeFirstDigit.value.orEmpty().trim()}${smsCodeSecondDigit.value.orEmpty().trim()}${smsCodeThirdDigit.value.orEmpty().trim()}${smsCodeLastDigit.value.orEmpty().trim()}"
|
||||
val identity = account.params.identityAddress
|
||||
if (identity != null) {
|
||||
Log.i(
|
||||
|
|
@ -519,7 +545,8 @@ class AccountCreationViewModel
|
|||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun requestFlexiApiToken() {
|
||||
private fun requestFlexiApiToken(requestAccountCreationToken: Boolean) {
|
||||
requestedTokenIsForAccountCreation = requestAccountCreationToken
|
||||
if (!coreContext.core.isPushNotificationAvailable) {
|
||||
Log.e(
|
||||
"$TAG Core says push notification aren't available, can't request a token from FlexiAPI"
|
||||
|
|
@ -545,11 +572,21 @@ class AccountCreationViewModel
|
|||
}
|
||||
|
||||
// Request an auth token, will be sent by push
|
||||
val request = accountManagerServices.createSendAccountCreationTokenByPushRequest(
|
||||
provider,
|
||||
param,
|
||||
prid
|
||||
)
|
||||
val request = if (requestAccountCreationToken) {
|
||||
Log.i("$TAG Requesting account creation token")
|
||||
accountManagerServices.createSendAccountCreationTokenByPushRequest(
|
||||
provider,
|
||||
param,
|
||||
prid
|
||||
)
|
||||
} else {
|
||||
Log.i("$TAG Requesting account recovery token")
|
||||
accountManagerServices.createSendAccountRecoveryTokenByPushRequest(
|
||||
provider,
|
||||
param,
|
||||
prid
|
||||
)
|
||||
}
|
||||
request.addListener(accountManagerServicesListener)
|
||||
request.submit()
|
||||
|
||||
|
|
@ -580,12 +617,6 @@ class AccountCreationViewModel
|
|||
private fun onFlexiApiTokenRequestError() {
|
||||
Log.e("$TAG Flexi API token request by push error!")
|
||||
operationInProgress.postValue(false)
|
||||
errorHappenedEvent.postValue(
|
||||
Event(
|
||||
AppUtils.getString(
|
||||
R.string.assistant_account_register_push_notification_not_received_error
|
||||
)
|
||||
)
|
||||
)
|
||||
showRedToast(R.string.assistant_account_register_push_notification_not_received_error, R.drawable.warning_circle)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
9
app/src/main/res/drawable/password.xml
Normal file
9
app/src/main/res/drawable/password.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:pathData="M48,56L48,200a8,8 0,0 1,-16 0L32,56a8,8 0,0 1,16 0ZM140,110.5L120,117L120,96a8,8 0,0 0,-16 0v21L84,110.5a8,8 0,0 0,-5 15.22l20,6.49 -12.34,17a8,8 0,1 0,12.94 9.4l12.34,-17 12.34,17a8,8 0,1 0,12.94 -9.4l-12.34,-17 20,-6.49A8,8 0,0 0,140 110.5ZM246,115.64A8,8 0,0 0,236 110.5L216,117L216,96a8,8 0,0 0,-16 0v21l-20,-6.49a8,8 0,0 0,-4.95 15.22l20,6.49 -12.34,17a8,8 0,1 0,12.94 9.4l12.34,-17 12.34,17a8,8 0,1 0,12.94 -9.4l-12.34,-17 20,-6.49A8,8 0,0 0,246 115.64Z"
|
||||
android:fillColor="#4e6074"/>
|
||||
</vector>
|
||||
181
app/src/main/res/layout/assistant_recover_account_fragment.xml
Normal file
181
app/src/main/res/layout/assistant_recover_account_fragment.xml
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:bind="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<import type="android.text.InputType" />
|
||||
<variable
|
||||
name="backClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="recoverEmailAccountClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="recoverPhoneNumberAccountClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="org.linphone.ui.assistant.viewmodel.AccountCreationViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/color_main2_000">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{backClickListener}"
|
||||
android:id="@+id/back"
|
||||
android:layout_width="@dimen/top_bar_height"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
android:contentDescription="@string/content_description_go_back_icon"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/assistant_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assistant_forgotten_password_title"
|
||||
android:textColor="?attr/color_text"
|
||||
app:layout_constraintTop_toTopOf="@id/back"
|
||||
app:layout_constraintBottom_toBottomOf="@id/back"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/password_icon"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="68dp"
|
||||
android:background="@drawable/circle_light_blue_button_background"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/password"
|
||||
android:contentDescription="@null"
|
||||
app:tint="?attr/color_main2_500"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/header_style"
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginStart="48dp"
|
||||
android:layout_marginEnd="48dp"
|
||||
android:textAlignment="center"
|
||||
android:text="@string/assistant_forgotten_password_subtitle"
|
||||
app:layout_constraintTop_toBottomOf="@id/password_icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style"
|
||||
android:id="@+id/message"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginStart="48dp"
|
||||
android:layout_marginEnd="48dp"
|
||||
android:text="@string/assistant_forgotten_password_message"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?attr/color_main2_600"
|
||||
android:gravity="center_horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@id/subtitle"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/primary_button_label_style"
|
||||
android:id="@+id/recover_email"
|
||||
android:onClick="@{recoverEmailAccountClickListener}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:text="@string/assistant_recover_email_account_label"
|
||||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/message" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/primary_button_label_style"
|
||||
android:id="@+id/recover_phone_number"
|
||||
android:onClick="@{recoverPhoneNumberAccountClickListener}"
|
||||
android:enabled="@{viewModel.pushNotificationsAvailable}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:text="@string/assistant_recover_phone_number_account_label"
|
||||
app:layout_constraintWidth_max="@dimen/button_max_width"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/recover_email" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/header_style"
|
||||
android:id="@+id/no_push_label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginStart="48dp"
|
||||
android:layout_marginEnd="48dp"
|
||||
android:textAlignment="center"
|
||||
android:visibility="@{viewModel.pushNotificationsAvailable ? View.GONE : View.VISIBLE, default=gone}"
|
||||
android:text="@string/assistant_recover_phone_number_account_unavailable_no_push_warning"
|
||||
app:layout_constraintTop_toBottomOf="@id/recover_phone_number"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/mountains"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:src="@drawable/mountains"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@null"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/no_push_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:tint="?attr/color_main1_500" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<include
|
||||
layout="@layout/operation_in_progress"
|
||||
bind:visibility="@{viewModel.operationInProgress}" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</layout>
|
||||
|
|
@ -134,6 +134,7 @@
|
|||
app:popEnterAnim="@anim/slide_in_left"
|
||||
app:popExitAnim="@anim/slide_out_right"
|
||||
app:launchSingleTop="true" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_landingFragment_to_thirdPartySipAccountLoginFragment"
|
||||
app:destination="@id/thirdPartySipAccountLoginFragment"
|
||||
|
|
@ -143,7 +144,8 @@
|
|||
app:popExitAnim="@anim/slide_out_right"
|
||||
app:launchSingleTop="true"
|
||||
app:popUpTo="@id/landingFragment"
|
||||
app:popUpToInclusive="true"/>
|
||||
app:popUpToInclusive="true" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_landingFragment_to_helpFragment"
|
||||
app:destination="@id/helpFragment"
|
||||
|
|
@ -152,7 +154,14 @@
|
|||
app:popEnterAnim="@anim/slide_in_left"
|
||||
app:popExitAnim="@anim/slide_out_right"
|
||||
app:launchSingleTop="true" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_landingFragment_to_recoverAccountFragment"
|
||||
app:destination="@id/recoverAccountFragment"
|
||||
app:enterAnim="@anim/slide_in_right"
|
||||
app:exitAnim="@anim/slide_out_left"
|
||||
app:popEnterAnim="@anim/slide_in_left"
|
||||
app:popExitAnim="@anim/slide_out_right"
|
||||
app:launchSingleTop="true" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
|
|
@ -198,4 +207,10 @@
|
|||
android:label="DebugFragment"
|
||||
tools:layout="@layout/help_debug_fragment"/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/recoverAccountFragment"
|
||||
android:name="org.linphone.ui.assistant.fragment.RecoverAccountFragment"
|
||||
android:label="RecoverAccountFragment"
|
||||
tools:layout="@layout/assistant_recover_account_fragment" />
|
||||
|
||||
</navigation>
|
||||
|
|
@ -141,6 +141,12 @@
|
|||
<string name="assistant_permissions_post_notifications_title"><b>Notifications :</b> Pour vous informer quand vous recevez un message ou un appel.</string>
|
||||
<string name="assistant_permissions_record_audio_title"><b>Microphone :</b> Pour permettre à vos correspondants de vous entendre.</string>
|
||||
<string name="assistant_permissions_access_camera_title"><b>Caméra :</b> Pour capturer votre vidéo lors des appels et des conférences.</string>
|
||||
<string name="assistant_forgotten_password_title">Récupération de compte</string>
|
||||
<string name="assistant_forgotten_password_subtitle">Choisissez comment récupérer votre compte.</string>
|
||||
<string name="assistant_forgotten_password_message">Vous avez créé votre compte avec :</string>
|
||||
<string name="assistant_recover_email_account_label">Un email</string>
|
||||
<string name="assistant_recover_phone_number_account_label">Un numéro de téléphone</string>
|
||||
<string name="assistant_recover_phone_number_account_unavailable_no_push_warning">Les notifications push ne semblent pas être disponibles sur votre appareil. Celles-ci sont nécessaires à la récupération d’un compte sur l’application mobile avec un numéro de téléphone.</string>
|
||||
|
||||
<!-- Main navigation items -->
|
||||
<string name="bottom_navigation_contacts_label">Contacts</string>
|
||||
|
|
@ -860,7 +866,7 @@
|
|||
|
||||
<!-- Keep <u></u> in the following strings translations! -->
|
||||
<string name="welcome_carousel_skip"><u>Passer</u></string>
|
||||
<string name="assistant_forgotten_password"><u>Mot de passe oublié ?</u></string>
|
||||
<string name="assistant_forgotten_password"><u>Mot de passe oublié ou inconnu ?</u></string>
|
||||
<string name="call_zrtp_sas_validation_skip"><u>Passer</u></string>
|
||||
|
||||
<!-- Keep <b></b> in the following strings translations! -->
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
<string name="website_privacy_policy_url" translatable="false">https://linphone.org/en/privacy-policy</string>
|
||||
<string name="website_terms_and_conditions_url" translatable="false">https://linphone.org/en/terms-of-use</string>
|
||||
<string name="web_platform_register_email_url" translatable="false">https://subscribe.linphone.org/register/email</string>
|
||||
<string name="web_platform_forgotten_password_url" translatable="false">https://subscribe.linphone.org/</string>
|
||||
<string name="web_platform_forgotten_password_url" translatable="false">https://subscribe.linphone.org</string>
|
||||
<string name="website_translate_weblate_url" translatable="false">https://weblate.linphone.org/</string>
|
||||
<string name="website_open_source_licences_usage_url" translatable="false">https://wiki.linphone.org/xwiki/wiki/public/view/Linphone/Third%20party%20components%20/#Hlinphone-android</string>
|
||||
<string name="conversation_end_to_end_encrypted_bottom_sheet_link" translatable="false"><u>https://linphone.org/en/features/#security</u></string>
|
||||
|
|
@ -183,6 +183,12 @@
|
|||
<string name="assistant_permissions_post_notifications_title"><b>Post notifications:</b> To be informed when you receive a message or a call.</string>
|
||||
<string name="assistant_permissions_record_audio_title"><b>Record audio:</b> So your correspondent can hear you and to record voice messages.</string>
|
||||
<string name="assistant_permissions_access_camera_title"><b>Access camera:</b> To capture video during video calls and conferences.</string>
|
||||
<string name="assistant_forgotten_password_title">Account recovery</string>
|
||||
<string name="assistant_forgotten_password_subtitle">Choose how to recover your account.</string>
|
||||
<string name="assistant_forgotten_password_message">You created your account using:</string>
|
||||
<string name="assistant_recover_email_account_label">An email</string>
|
||||
<string name="assistant_recover_phone_number_account_label">A phone number</string>
|
||||
<string name="assistant_recover_phone_number_account_unavailable_no_push_warning">Push notifications do not seem to be available on your device, but they are mandatory for recovering a phone number account in the mobile app.</string>
|
||||
|
||||
<!-- Main navigation items -->
|
||||
<string name="bottom_navigation_contacts_label">Contacts</string>
|
||||
|
|
@ -903,7 +909,7 @@
|
|||
|
||||
<!-- Keep <u></u> in the following strings translations! -->
|
||||
<string name="welcome_carousel_skip"><u>Skip</u></string>
|
||||
<string name="assistant_forgotten_password"><u>Forgotten password?</u></string>
|
||||
<string name="assistant_forgotten_password"><u>Forgotten or unknown password?</u></string>
|
||||
<string name="call_zrtp_sas_validation_skip"><u>Skip</u></string>
|
||||
|
||||
<!-- Keep <b></b> in the following strings translations! -->
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue