Merge branch 'fix/test_plan' into 'release/6.2'

Fix/test plan

See merge request BC/public/linphone-android!2479
This commit is contained in:
Sylvain Berfini 2026-04-03 13:15:33 +00:00
commit 216d874031
17 changed files with 112 additions and 29 deletions

View file

@ -28,12 +28,13 @@ import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.linphone.BR.showTransferIcon
import org.linphone.R import org.linphone.R
import org.linphone.databinding.CallListCellBinding import org.linphone.databinding.CallListCellBinding
import org.linphone.ui.call.model.CallModel import org.linphone.ui.call.model.CallModel
import org.linphone.utils.Event import org.linphone.utils.Event
class CallsListAdapter : class CallsListAdapter(private val showTransferIconInsteadOfCallState: Boolean = false) :
ListAdapter<CallModel, RecyclerView.ViewHolder>(CallDiffCallback()) { ListAdapter<CallModel, RecyclerView.ViewHolder>(CallDiffCallback()) {
var selectedAdapterPosition = -1 var selectedAdapterPosition = -1
@ -55,6 +56,7 @@ class CallsListAdapter :
val viewHolder = ViewHolder(binding) val viewHolder = ViewHolder(binding)
binding.apply { binding.apply {
lifecycleOwner = parent.findViewTreeLifecycleOwner() lifecycleOwner = parent.findViewTreeLifecycleOwner()
showTransferIcon = showTransferIconInsteadOfCallState
setOnClickListener { setOnClickListener {
callClickedEvent.value = Event(model!!) callClickedEvent.value = Event(model!!)

View file

@ -228,6 +228,7 @@ class NewCallFragment : GenericCallFragment() {
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
viewModel.searchFilter.value = ""
numberOrAddressPickerDialog?.dismiss() numberOrAddressPickerDialog?.dismiss()
numberOrAddressPickerDialog = null numberOrAddressPickerDialog = null
} }

View file

@ -87,7 +87,7 @@ class TransferCallFragment : GenericCallFragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
callsAdapter = CallsListAdapter() callsAdapter = CallsListAdapter(showTransferIconInsteadOfCallState = true)
contactsAdapter = ConversationsContactsAndSuggestionsListAdapter() contactsAdapter = ConversationsContactsAndSuggestionsListAdapter()
} }
@ -249,6 +249,7 @@ class TransferCallFragment : GenericCallFragment() {
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
viewModel.searchFilter.value = ""
numberOrAddressPickerDialog?.dismiss() numberOrAddressPickerDialog?.dismiss()
numberOrAddressPickerDialog = null numberOrAddressPickerDialog = null
} }

View file

@ -866,6 +866,8 @@ class CurrentCallViewModel
isRecording.postValue(recording) isRecording.postValue(recording)
if (recording) { if (recording) {
showRecordingToast() showRecordingToast()
} else {
showGreenToast(R.string.call_has_been_recorded, R.drawable.record_fill)
} }
} }
} }

View file

@ -548,6 +548,26 @@ open class ConversationFragment : SlidingPaneChildFragment() {
} }
} }
} }
sharedViewModel.textToShareFromIntent.observe(viewLifecycleOwner) { text ->
if (text.isNotEmpty() && sharedViewModel.displayedChatRoom != null) {
Log.i("$TAG Found text to share from intent")
sendMessageViewModel.textToSend.value = text
sharedViewModel.textToShareFromIntent.value = ""
}
}
sharedViewModel.filesToShareFromIntent.observe(viewLifecycleOwner) { files ->
if (files.isNotEmpty() && sharedViewModel.displayedChatRoom != null) {
Log.i("$TAG Found [${files.size}] files to share from intent")
for (path in files) {
sendMessageViewModel.addAttachments(arrayListOf(path))
}
sharedViewModel.filesToShareFromIntent.value = arrayListOf()
}
}
} }
} }
} }
@ -1001,26 +1021,6 @@ open class ConversationFragment : SlidingPaneChildFragment() {
} }
} }
sharedViewModel.textToShareFromIntent.observe(viewLifecycleOwner) { text ->
if (text.isNotEmpty() && sharedViewModel.displayedChatRoom != null) {
Log.i("$TAG Found text to share from intent")
sendMessageViewModel.textToSend.value = text
sharedViewModel.textToShareFromIntent.value = ""
}
}
sharedViewModel.filesToShareFromIntent.observe(viewLifecycleOwner) { files ->
if (files.isNotEmpty()) {
Log.i("$TAG Found [${files.size}] files to share from intent")
for (path in files) {
sendMessageViewModel.addAttachments(arrayListOf(path))
}
sharedViewModel.filesToShareFromIntent.value = arrayListOf()
}
}
sharedViewModel.forceRefreshConversationInfoEvent.observe(viewLifecycleOwner) { sharedViewModel.forceRefreshConversationInfoEvent.observe(viewLifecycleOwner) {
it.consume { it.consume {
Log.i("$TAG Force refreshing conversation info") Log.i("$TAG Force refreshing conversation info")

View file

@ -212,6 +212,7 @@ class LdapViewModel : GenericViewModel() {
core.addLdap(ldap) core.addLdap(ldap)
Log.i("$TAG New LDAP config created") Log.i("$TAG New LDAP config created")
} }
showGreenToast(R.string.settings_contacts_ldap_saved_toast, R.drawable.check)
ldapServerOperationSuccessfulEvent.postValue(Event(true)) ldapServerOperationSuccessfulEvent.postValue(Event(true))
} catch (e: Exception) { } catch (e: Exception) {
Log.e("$TAG Exception while creating LDAP: $e") Log.e("$TAG Exception while creating LDAP: $e")

View file

@ -142,7 +142,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="15dp" android:layout_margin="15dp"
android:text="@string/call_do_zrtp_sas_validation_again" android:text="@string/call_do_zrtp_sas_validation_again"
android:visibility="@{model.isMediaEncryptionZrtp ? View.VISIBLE : View.GONE}" android:visibility="@{model.isMediaEncryptionZrtp &amp;&amp; !viewModel.conferenceModel.isCurrentCallInConference() ? View.VISIBLE : View.GONE}"
app:layout_columnSpan="2" app:layout_columnSpan="2"
app:layout_gravity="center_horizontal"/> app:layout_gravity="center_horizontal"/>

View file

@ -32,6 +32,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="no_meeting_image, no_meeting_label"
android:visibility="@{viewModel.meetings.empty &amp;&amp; !viewModel.isFilterEmpty ? View.VISIBLE : View.GONE, default=gone}" />
<include <include
android:id="@+id/bottom_nav_bar" android:id="@+id/bottom_nav_bar"
android:layout_width="@dimen/landscape_nav_bar_width" android:layout_width="@dimen/landscape_nav_bar_width"
@ -63,6 +69,33 @@
android:layout_marginTop="@dimen/top_bar_height" android:layout_marginTop="@dimen/top_bar_height"
android:layout_marginStart="@dimen/landscape_nav_bar_width" /> android:layout_marginStart="@dimen/landscape_nav_bar_width" />
<ImageView
android:id="@+id/no_meeting_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="@drawable/illu"
android:contentDescription="@null"
app:layout_constraintHeight_max="200dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
app:layout_constraintTop_toBottomOf="@id/top_bar"
app:layout_constraintBottom_toTopOf="@id/no_meeting_label" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/section_header_style"
android:id="@+id/no_meeting_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/list_filter_no_result_found"
android:textAlignment="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
app:layout_constraintTop_toBottomOf="@id/no_meeting_image"
app:layout_constraintBottom_toBottomOf="parent"/>
<com.google.android.material.progressindicator.CircularProgressIndicator <com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/fetch_in_progress" android:id="@+id/fetch_in_progress"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -285,7 +285,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="15dp" android:paddingBottom="15dp"
android:text="@string/call_action_record_call" android:text="@{viewModel.isRecording ? @string/call_action_stop_record_call : @string/call_action_record_call, default=@string/call_action_record_call}"
android:labelFor="@id/record_call" android:labelFor="@id/record_call"
app:layout_constraintTop_toBottomOf="@id/record_call" app:layout_constraintTop_toBottomOf="@id/record_call"
app:layout_constraintStart_toStartOf="@id/calls_list_label" app:layout_constraintStart_toStartOf="@id/calls_list_label"

View file

@ -14,6 +14,9 @@
<variable <variable
name="model" name="model"
type="org.linphone.ui.call.model.CallModel" /> type="org.linphone.ui.call.model.CallModel" />
<variable
name="showTransferIcon"
type="Boolean" />
</data> </data>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
@ -55,7 +58,7 @@
android:layout_height="24dp" android:layout_height="24dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:contentDescription="@null" android:contentDescription="@null"
android:src="@{model.isPaused ? @drawable/phone_pause : @drawable/phone_call, default=@drawable/phone_pause}" android:src="@{showTransferIcon ? @drawable/phone_transfer : model.isPaused ? @drawable/phone_pause : @drawable/phone_call, default=@drawable/phone_pause}"
app:tint="?attr/color_main2_500" app:tint="?attr/color_main2_500"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -70,6 +73,7 @@
android:text="@{model.state, default=`Paused`}" android:text="@{model.state, default=`Paused`}"
android:textSize="12sp" android:textSize="12sp"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:visibility="@{showTransferIcon ? View.GONE : View.VISIBLE}"
app:layout_constraintHorizontal_bias="1" app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toEndOf="@id/name" app:layout_constraintStart_toEndOf="@id/name"
app:layout_constraintEnd_toStartOf="@id/call_state_icon" app:layout_constraintEnd_toStartOf="@id/call_state_icon"

View file

@ -136,7 +136,7 @@
android:layout_margin="15dp" android:layout_margin="15dp"
android:text="@string/call_do_zrtp_sas_validation_again" android:text="@string/call_do_zrtp_sas_validation_again"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:visibility="@{model.isMediaEncryptionZrtp ? View.VISIBLE : View.GONE}"/> android:visibility="@{model.isMediaEncryptionZrtp &amp;&amp; !viewModel.conferenceModel.isCurrentCallInConference() ? View.VISIBLE : View.GONE}"/>
</LinearLayout> </LinearLayout>

View file

@ -352,7 +352,7 @@
android:onClick="@{() -> viewModel.toggleParticipantsExpand()}" android:onClick="@{() -> viewModel.toggleParticipantsExpand()}"
android:padding="10dp" android:padding="10dp"
android:text="@{viewModel.participantsLabel, default=@string/conversation_info_participants_list_title}" android:text="@{viewModel.participantsLabel, default=@string/conversation_info_participants_list_title}"
android:visibility="@{viewModel.isGroup ? View.VISIBLE : View.GONE}" android:visibility="@{viewModel.isGroup &amp;&amp; !viewModel.isReadOnly ? View.VISIBLE : View.GONE}"
android:background="@drawable/squircle_transparent_button_background" android:background="@drawable/squircle_transparent_button_background"
app:layout_constraintWidth_max="@dimen/section_max_width" app:layout_constraintWidth_max="@dimen/section_max_width"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View file

@ -259,7 +259,7 @@
android:text="@={viewModel.description}" android:text="@={viewModel.description}"
android:textSize="14sp" android:textSize="14sp"
android:textColor="?attr/color_main2_600" android:textColor="?attr/color_main2_600"
android:inputType="text|textCapSentences" android:inputType="text|textCapSentences|textMultiLine"
android:drawableStart="@drawable/file_text" android:drawableStart="@drawable/file_text"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:drawableTint="?attr/color_main2_600" android:drawableTint="?attr/color_main2_600"

View file

@ -397,7 +397,7 @@
android:text="@={viewModel.description}" android:text="@={viewModel.description}"
android:textSize="14sp" android:textSize="14sp"
android:textColor="?attr/color_main2_600" android:textColor="?attr/color_main2_600"
android:inputType="text|textCapSentences" android:inputType="text|textCapSentences|textMultiLine"
android:drawableStart="@drawable/file_text" android:drawableStart="@drawable/file_text"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:drawableTint="?attr/color_main2_600" android:drawableTint="?attr/color_main2_600"

View file

@ -33,6 +33,12 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/color_main1_500"> android:background="?attr/color_main1_500">
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="no_meeting_image, no_meeting_label"
android:visibility="@{viewModel.meetings.empty &amp;&amp; !viewModel.isFilterEmpty ? View.VISIBLE : View.GONE, default=gone}" />
<include <include
android:id="@+id/top_bar" android:id="@+id/top_bar"
layout="@layout/main_activity_top_bar" layout="@layout/main_activity_top_bar"
@ -64,6 +70,33 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/bottom_nav_bar" /> app:layout_constraintBottom_toTopOf="@id/bottom_nav_bar" />
<ImageView
android:id="@+id/no_meeting_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="@drawable/illu"
android:contentDescription="@null"
app:layout_constraintHeight_max="200dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/meetings_list"
app:layout_constraintBottom_toTopOf="@id/no_meeting_label" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/section_header_style"
android:id="@+id/no_meeting_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/list_filter_no_result_found"
android:textAlignment="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/no_meeting_image"
app:layout_constraintBottom_toBottomOf="@id/meetings_list"/>
<com.google.android.material.progressindicator.CircularProgressIndicator <com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/fetch_in_progress" android:id="@+id/fetch_in_progress"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -266,6 +266,7 @@
<string name="settings_contacts_ldap_name_attributes_title">Attributs de nom</string> <string name="settings_contacts_ldap_name_attributes_title">Attributs de nom</string>
<string name="settings_contacts_ldap_sip_attributes_title">Attributs SIP</string> <string name="settings_contacts_ldap_sip_attributes_title">Attributs SIP</string>
<string name="settings_contacts_ldap_sip_domain_title">Domaine SIP</string> <string name="settings_contacts_ldap_sip_domain_title">Domaine SIP</string>
<string name="settings_contacts_ldap_saved_toast">Configuration LDAP sauvegardée</string>
<string name="settings_contacts_ldap_error_toast">Une erreur s\'est produite, la configuration LDAP n\'a pas été sauvegardée !</string> <string name="settings_contacts_ldap_error_toast">Une erreur s\'est produite, la configuration LDAP n\'a pas été sauvegardée !</string>
<string name="settings_contacts_ldap_empty_field_error_toast">Tous les champs doivent être remplis</string> <string name="settings_contacts_ldap_empty_field_error_toast">Tous les champs doivent être remplis</string>
<string name="settings_meetings_title">Réunions</string> <string name="settings_meetings_title">Réunions</string>
@ -712,6 +713,7 @@
<string name="call_action_pause_call">Mettre en pause</string> <string name="call_action_pause_call">Mettre en pause</string>
<string name="call_action_resume_call">Reprendre</string> <string name="call_action_resume_call">Reprendre</string>
<string name="call_action_record_call">Enregistrer</string> <string name="call_action_record_call">Enregistrer</string>
<string name="call_action_stop_record_call">Arrêter l\'enregistrement</string>
<string name="call_action_hang_up">Raccrocher</string> <string name="call_action_hang_up">Raccrocher</string>
<string name="call_action_decline">Décliner</string> <string name="call_action_decline">Décliner</string>
<string name="call_action_answer">Décrocher</string> <string name="call_action_answer">Décrocher</string>
@ -734,6 +736,7 @@
<string name="call_not_encrypted">Appel non chiffré</string> <string name="call_not_encrypted">Appel non chiffré</string>
<string name="calls_list_title">Liste des appels</string> <string name="calls_list_title">Liste des appels</string>
<string name="call_is_being_recorded">L\'appel est enregistré</string> <string name="call_is_being_recorded">L\'appel est enregistré</string>
<string name="call_has_been_recorded">Enregistrement sauvegardé</string>
<string name="call_remote_is_recording">%s enregistre l\'appel</string> <string name="call_remote_is_recording">%s enregistre l\'appel</string>
<string name="calls_count_label">%s appels</string> <string name="calls_count_label">%s appels</string>
<string name="calls_paused_count_label">%s appels en pause</string> <string name="calls_paused_count_label">%s appels en pause</string>

View file

@ -308,6 +308,7 @@
<string name="settings_contacts_ldap_name_attributes_title">Name attributes</string> <string name="settings_contacts_ldap_name_attributes_title">Name attributes</string>
<string name="settings_contacts_ldap_sip_attributes_title">SIP attributes</string> <string name="settings_contacts_ldap_sip_attributes_title">SIP attributes</string>
<string name="settings_contacts_ldap_sip_domain_title">SIP domain</string> <string name="settings_contacts_ldap_sip_domain_title">SIP domain</string>
<string name="settings_contacts_ldap_saved_toast">LDAP server saved</string>
<string name="settings_contacts_ldap_error_toast">A error occurred, LDAP server not saved!</string> <string name="settings_contacts_ldap_error_toast">A error occurred, LDAP server not saved!</string>
<string name="settings_contacts_ldap_empty_field_error_toast">All fields must be filled</string> <string name="settings_contacts_ldap_empty_field_error_toast">All fields must be filled</string>
<string name="settings_meetings_title">Meetings</string> <string name="settings_meetings_title">Meetings</string>
@ -755,6 +756,7 @@
<string name="call_action_pause_call">Pause</string> <string name="call_action_pause_call">Pause</string>
<string name="call_action_resume_call">Resume</string> <string name="call_action_resume_call">Resume</string>
<string name="call_action_record_call">Record</string> <string name="call_action_record_call">Record</string>
<string name="call_action_stop_record_call">Stop recording</string>
<string name="call_action_hang_up">Hang up</string> <string name="call_action_hang_up">Hang up</string>
<string name="call_action_decline">Decline</string> <string name="call_action_decline">Decline</string>
<string name="call_action_answer">Answer</string> <string name="call_action_answer">Answer</string>
@ -777,6 +779,7 @@
<string name="call_not_encrypted">Call is not encrypted</string> <string name="call_not_encrypted">Call is not encrypted</string>
<string name="calls_list_title">Calls list</string> <string name="calls_list_title">Calls list</string>
<string name="call_is_being_recorded">Call is being recorded</string> <string name="call_is_being_recorded">Call is being recorded</string>
<string name="call_has_been_recorded">Call recording has been saved</string>
<string name="call_remote_is_recording">%s is recording</string> <string name="call_remote_is_recording">%s is recording</string>
<string name="calls_count_label">%s calls</string> <string name="calls_count_label">%s calls</string>
<string name="calls_paused_count_label">%s paused calls</string> <string name="calls_paused_count_label">%s paused calls</string>