Added advanced account setting to manually update password

This commit is contained in:
Sylvain Berfini 2024-08-29 13:43:46 +02:00
parent 5d7addb8d8
commit 5a7872222d
17 changed files with 315 additions and 32 deletions

View file

@ -63,8 +63,8 @@ import org.linphone.databinding.MainActivityBinding
import org.linphone.ui.GenericActivity
import org.linphone.ui.assistant.AssistantActivity
import org.linphone.ui.main.chat.fragment.ConversationsListFragmentDirections
import org.linphone.ui.main.fragment.AuthRequestedDialogModel
import org.linphone.ui.main.help.fragment.DebugFragmentDirections
import org.linphone.ui.main.model.AuthRequestedDialogModel
import org.linphone.ui.main.sso.fragment.SingleSignOnFragmentDirections
import org.linphone.ui.main.viewmodel.MainViewModel
import org.linphone.ui.main.viewmodel.SharedMainViewModel

View file

@ -43,9 +43,9 @@ import org.linphone.ui.GenericActivity
import org.linphone.ui.main.chat.adapter.ConversationParticipantsAdapter
import org.linphone.ui.main.chat.model.ParticipantModel
import org.linphone.ui.main.chat.viewmodel.ConversationInfoViewModel
import org.linphone.ui.main.fragment.GroupSetOrEditSubjectDialogModel
import org.linphone.ui.main.fragment.SlidingPaneChildFragment
import org.linphone.ui.main.history.model.ConfirmationDialogModel
import org.linphone.ui.main.model.GroupSetOrEditSubjectDialogModel
import org.linphone.utils.DialogUtils
import org.linphone.utils.Event

View file

@ -35,7 +35,7 @@ import org.linphone.databinding.StartChatFragmentBinding
import org.linphone.ui.GenericActivity
import org.linphone.ui.main.chat.viewmodel.StartConversationViewModel
import org.linphone.ui.main.fragment.GenericAddressPickerFragment
import org.linphone.ui.main.fragment.GroupSetOrEditSubjectDialogModel
import org.linphone.ui.main.model.GroupSetOrEditSubjectDialogModel
import org.linphone.utils.DialogUtils
import org.linphone.utils.Event
import org.linphone.utils.hideKeyboard

View file

@ -38,8 +38,8 @@ import org.linphone.core.tools.Log
import org.linphone.databinding.StartCallFragmentBinding
import org.linphone.ui.GenericActivity
import org.linphone.ui.main.fragment.GenericAddressPickerFragment
import org.linphone.ui.main.fragment.GroupSetOrEditSubjectDialogModel
import org.linphone.ui.main.history.viewmodel.StartCallViewModel
import org.linphone.ui.main.model.GroupSetOrEditSubjectDialogModel
import org.linphone.utils.DialogUtils
import org.linphone.utils.Event
import org.linphone.utils.addCharacterAtPosition

View file

@ -17,7 +17,7 @@
* 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.main.fragment
package org.linphone.ui.main.model
import androidx.annotation.UiThread
import androidx.lifecycle.MutableLiveData

View file

@ -17,7 +17,7 @@
* 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.main.fragment
package org.linphone.ui.main.model
import androidx.annotation.UiThread
import androidx.lifecycle.MediatorLiveData

View file

@ -37,7 +37,9 @@ import org.linphone.core.tools.Log
import org.linphone.databinding.AccountSettingsFragmentBinding
import org.linphone.ui.GenericActivity
import org.linphone.ui.main.fragment.GenericMainFragment
import org.linphone.ui.main.settings.model.UpdatePasswordDialogModel
import org.linphone.ui.main.settings.viewmodel.AccountSettingsViewModel
import org.linphone.utils.DialogUtils
import org.linphone.utils.Event
@UiThread
@ -99,6 +101,10 @@ class AccountSettingsFragment : GenericMainFragment() {
goBack()
}
binding.setUpdatePasswordClickListener {
showUpdatePasswordDialog()
}
viewModel.accountFoundEvent.observe(viewLifecycleOwner) {
it.consume { found ->
if (found) {
@ -140,4 +146,24 @@ class AccountSettingsFragment : GenericMainFragment() {
// It is possible some value have changed, causing some menu to appear or disappear
sharedViewModel.forceUpdateAvailableNavigationItems.value = Event(true)
}
private fun showUpdatePasswordDialog() {
val model = UpdatePasswordDialogModel()
val dialog = DialogUtils.getUpdatePasswordDialog(requireContext(), model)
model.dismissEvent.observe(viewLifecycleOwner) {
it.consume {
dialog.dismiss()
}
}
model.confirmEvent.observe(viewLifecycleOwner) {
it.consume { password ->
viewModel.updateAccountPassword(password)
dialog.dismiss()
}
}
dialog.show()
}
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2010-2024 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.main.settings.model
import androidx.annotation.UiThread
import androidx.lifecycle.MutableLiveData
import org.linphone.utils.Event
@UiThread
class UpdatePasswordDialogModel {
val password = MutableLiveData<String>()
val showPassword = MutableLiveData<Boolean>()
val dismissEvent = MutableLiveData<Event<Boolean>>()
val confirmEvent = MutableLiveData<Event<String>>()
init {
showPassword.value = false
}
@UiThread
fun toggleShowPassword() {
showPassword.value = showPassword.value == false
}
@UiThread
fun dismiss() {
dismissEvent.value = Event(true)
}
@UiThread
fun confirm() {
confirmEvent.value = Event(password.value.orEmpty())
}
}

View file

@ -77,6 +77,8 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() {
val accountFoundEvent = MutableLiveData<Event<Boolean>>()
val showUpdatePasswordDialog = MutableLiveData<Event<String>>()
private lateinit var account: Account
private lateinit var natPolicy: NatPolicy
@ -242,4 +244,25 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() {
fun toggleAdvancedSettingsExpand() {
expandAdvancedSettings.value = expandAdvancedSettings.value == false
}
@UiThread
fun updateAccountPassword(newPassword: String) {
coreContext.postOnCoreThread { core ->
if (::account.isInitialized) {
val authInfo = account.findAuthInfo()
if (authInfo != null) {
Log.i(
"$TAG Updating password for username [${authInfo.username}] using auth info [$authInfo]"
)
authInfo.password = newPassword
core.addAuthInfo(authInfo)
core.refreshRegisters()
} else {
Log.w(
"$TAG Failed to find auth info for account [${account.params.identityAddress?.asStringUriOnly()}]"
)
}
}
}
}
}

View file

@ -50,6 +50,7 @@ import org.linphone.databinding.DialogRemoveAllCallLogsBinding
import org.linphone.databinding.DialogRemoveCallLogsBinding
import org.linphone.databinding.DialogRemoveConversationHistoryBinding
import org.linphone.databinding.DialogSetOrEditGroupSubjectBindingImpl
import org.linphone.databinding.DialogUpdateAccountPasswordAfterRegisterFailureBinding
import org.linphone.databinding.DialogUpdateAccountPasswordBinding
import org.linphone.databinding.DialogUpdateAvailableBinding
import org.linphone.databinding.DialogZrtpSasValidationBinding
@ -61,9 +62,10 @@ import org.linphone.ui.call.model.ZrtpSasConfirmationDialogModel
import org.linphone.ui.main.contacts.model.ContactTrustDialogModel
import org.linphone.ui.main.contacts.model.NumberOrAddressPickerDialogModel
import org.linphone.ui.main.contacts.model.TrustCallDialogModel
import org.linphone.ui.main.fragment.AuthRequestedDialogModel
import org.linphone.ui.main.fragment.GroupSetOrEditSubjectDialogModel
import org.linphone.ui.main.history.model.ConfirmationDialogModel
import org.linphone.ui.main.model.AuthRequestedDialogModel
import org.linphone.ui.main.model.GroupSetOrEditSubjectDialogModel
import org.linphone.ui.main.settings.model.UpdatePasswordDialogModel
class DialogUtils {
companion object {
@ -335,6 +337,23 @@ class DialogUtils {
fun getAuthRequestedDialog(
context: Context,
viewModel: AuthRequestedDialogModel
): Dialog {
val binding: DialogUpdateAccountPasswordAfterRegisterFailureBinding = DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.dialog_update_account_password_after_register_failure,
null,
false
)
binding.viewModel = viewModel
binding.lifecycleOwner = context as LifecycleOwner
return getDialog(context, binding)
}
@UiThread
fun getUpdatePasswordDialog(
context: Context,
viewModel: UpdatePasswordDialogModel
): Dialog {
val binding: DialogUpdateAccountPasswordBinding = DataBindingUtil.inflate(
LayoutInflater.from(context),

View file

@ -5,6 +5,9 @@
<data>
<import type="android.view.View" />
<variable
name="updatePasswordClickListener"
type="View.OnClickListener" />
<variable
name="viewModel"
type="org.linphone.ui.main.settings.viewmodel.AccountSettingsViewModel" />
@ -371,7 +374,6 @@
android:layout_height="50dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="@dimen/screen_bottom_margin"
android:background="@drawable/edit_text_background"
android:paddingStart="20dp"
android:paddingEnd="20dp"
@ -382,6 +384,32 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/lime_server_title"
app:layout_constraintBottom_toTopOf="@id/update_password"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/update_password"
android:onClick="@{updatePasswordClickListener}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="@dimen/screen_bottom_margin"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:text="@string/account_settings_update_password_title"
android:maxLines="1"
android:ellipsize="end"
android:drawableEnd="@drawable/caret_right"
android:drawableTint="?attr/color_main2_600"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/lime_server"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -8,6 +8,9 @@
<variable
name="backClickListener"
type="View.OnClickListener" />
<variable
name="updatePasswordClickListener"
type="View.OnClickListener" />
<variable
name="viewModel"
type="org.linphone.ui.main.settings.viewmodel.AccountSettingsViewModel" />
@ -157,8 +160,8 @@
android:hint="@string/account_settings_mwi_uri_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/mwi_uri_title"/>
app:layout_constraintTop_toBottomOf="@id/mwi_uri_title"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
@ -186,6 +189,7 @@
android:layout_marginBottom="@dimen/screen_bottom_margin"
android:visibility="@{viewModel.expandAdvancedSettings ? View.VISIBLE : View.GONE}"
layout="@layout/account_advanced_settings"
bind:updatePasswordClickListener="@{updatePasswordClickListener}"
bind:viewModel="@{viewModel}"/>
</LinearLayout>

View file

@ -7,7 +7,7 @@
<import type="android.view.View" />
<variable
name="viewModel"
type="org.linphone.ui.main.fragment.GroupSetOrEditSubjectDialogModel" />
type="org.linphone.ui.main.model.GroupSetOrEditSubjectDialogModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout

View file

@ -8,7 +8,7 @@
<import type="android.text.InputType" />
<variable
name="viewModel"
type="org.linphone.ui.main.fragment.AuthRequestedDialogModel" />
type="org.linphone.ui.main.settings.model.UpdatePasswordDialogModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
@ -38,28 +38,12 @@
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:paddingTop="@dimen/dialog_top_bottom_margin"
android:text="@string/account_settings_dialog_invalid_password_title"
android:text="@string/account_settings_update_password_title"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintBottom_toTopOf="@id/message"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style_500"
android:id="@+id/message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="10dp"
android:text="@{viewModel.message, default=@string/account_settings_dialog_invalid_password_message}"
android:textAlignment="center"
app:layout_constraintWidth_max="@dimen/text_input_max_width"
app:layout_constraintBottom_toTopOf="@id/password"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/title" />
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatEditText
style="@style/default_text_style"
@ -83,7 +67,7 @@
app:layout_constraintBottom_toTopOf="@id/cancel"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/message"/>
app:layout_constraintTop_toBottomOf="@id/title"/>
<ImageView
android:id="@+id/eye"

View file

@ -0,0 +1,143 @@
<?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">
<data>
<import type="android.view.View" />
<import type="android.text.InputType" />
<variable
name="viewModel"
type="org.linphone.ui.main.model.AuthRequestedDialogModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:onClick="@{() -> viewModel.dismiss()}"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/dialog_background"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="2dp"
android:src="@drawable/shape_dialog_background"
android:contentDescription="@null"
app:layout_constraintWidth_max="@dimen/dialog_max_width"
app:layout_constraintBottom_toBottomOf="@id/anchor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/title" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/section_header_style"
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:paddingTop="@dimen/dialog_top_bottom_margin"
android:text="@string/account_settings_dialog_invalid_password_title"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintBottom_toTopOf="@id/message"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style_500"
android:id="@+id/message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="10dp"
android:text="@{viewModel.message, default=@string/account_settings_dialog_invalid_password_message}"
android:textAlignment="center"
app:layout_constraintWidth_max="@dimen/text_input_max_width"
app:layout_constraintBottom_toTopOf="@id/password"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/title" />
<androidx.appcompat.widget.AppCompatEditText
style="@style/default_text_style"
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="16dp"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:hint="@string/account_settings_dialog_invalid_password_hint"
android:text="@={viewModel.password}"
android:textSize="14sp"
android:textColor="?attr/color_main2_600"
android:maxLines="1"
android:background="@drawable/edit_text_background"
android:inputType="@{viewModel.showPassword ? InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD : InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD, default=textPassword}"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_max="@dimen/text_input_max_width"
app:layout_constraintBottom_toTopOf="@id/cancel"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/message"/>
<ImageView
android:id="@+id/eye"
android:onClick="@{() -> viewModel.toggleShowPassword()}"
android:layout_width="@dimen/icon_size"
android:layout_height="0dp"
android:padding="4dp"
android:layout_marginEnd="20dp"
android:contentDescription="@string/content_description_toggle_password_visibility"
android:src="@{viewModel.showPassword ? @drawable/eye_slash : @drawable/eye, default=@drawable/eye}"
app:tint="?attr/color_main2_500"
app:layout_constraintEnd_toEndOf="@id/password"
app:layout_constraintTop_toTopOf="@id/password"
app:layout_constraintBottom_toBottomOf="@id/password" />
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{() -> viewModel.dismiss()}"
style="@style/secondary_button_label_style"
android:id="@+id/cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:text="@string/dialog_cancel"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/password"
app:layout_constraintBottom_toTopOf="@id/confirm"/>
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{() -> viewModel.confirm()}"
style="@style/primary_button_label_style"
android:id="@+id/confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:text="@string/conversation_dialog_edit_subject_confirm_button"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintTop_toBottomOf="@id/cancel"
app:layout_constraintBottom_toTopOf="@id/anchor"/>
<View
android:id="@+id/anchor"
android:layout_width="wrap_content"
android:layout_height="@dimen/dialog_top_bottom_margin"
app:layout_constraintTop_toBottomOf="@id/confirm"
app:layout_constraintStart_toStartOf="@id/dialog_background"
app:layout_constraintEnd_toEndOf="@id/dialog_background"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -295,6 +295,7 @@
<string name="account_settings_bundle_mode_title">Mode "bundle"</string>
<string name="account_settings_cpim_in_basic_conversations_title">Utiliser CPIM dans les conversations \"basiques\"</string>
<string name="account_settings_mwi_uri_title">URI du serveur de messagerie vocale</string>
<string name="account_settings_update_password_title">Mettre à jour le mot de passe</string>
<string name="account_settings_dialog_invalid_password_title">Autentification requise</string>
<string name="account_settings_dialog_invalid_password_message">La connexion a échoué pour le compte \n%s.\n\nVous pouvez renseigner votre mot de passe à nouveau ou bien vérifier les options de configuration de votre compte.</string>

View file

@ -332,6 +332,7 @@
<string name="account_settings_bundle_mode_title">Bundle mode</string>
<string name="account_settings_cpim_in_basic_conversations_title">Use CPIM in \"basic\" conversations</string>
<string name="account_settings_mwi_uri_title">Voicemail URI</string>
<string name="account_settings_update_password_title">Update password</string>
<string name="account_settings_dialog_invalid_password_title">Authentication needed</string>
<string name="account_settings_dialog_invalid_password_message">Connection failed because authentication is missing or invalid for account \n%s.\n\nYou can provide password again, or check your account configuration in the settings.</string>