mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Added start group call feature from start call fragment
This commit is contained in:
parent
260ad798ed
commit
44af8bb340
13 changed files with 230 additions and 39 deletions
|
|
@ -38,9 +38,9 @@ import org.linphone.databinding.ChatInfoFragmentBinding
|
|||
import org.linphone.databinding.ChatParticipantAdminPopupMenuBinding
|
||||
import org.linphone.ui.main.MainActivity
|
||||
import org.linphone.ui.main.chat.adapter.ConversationParticipantsAdapter
|
||||
import org.linphone.ui.main.chat.model.ConversationSetOrEditSubjectDialogModel
|
||||
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.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
|
@ -217,9 +217,9 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
|||
|
||||
binding.setEditSubjectClickListener {
|
||||
val currentSubject = viewModel.subject.value.orEmpty()
|
||||
val model = ConversationSetOrEditSubjectDialogModel(currentSubject)
|
||||
val model = GroupSetOrEditSubjectDialogModel(currentSubject, isGroupConversation = true)
|
||||
|
||||
val dialog = DialogUtils.getSetOrEditConversationSubjectDialog(
|
||||
val dialog = DialogUtils.getSetOrEditGroupSubjectDialog(
|
||||
requireContext(),
|
||||
model
|
||||
)
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ import org.linphone.core.Friend
|
|||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.StartChatFragmentBinding
|
||||
import org.linphone.ui.main.MainActivity
|
||||
import org.linphone.ui.main.chat.model.ConversationSetOrEditSubjectDialogModel
|
||||
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.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.hideKeyboard
|
||||
|
|
@ -122,9 +122,9 @@ class StartConversationFragment : GenericAddressPickerFragment() {
|
|||
}
|
||||
|
||||
private fun showGroupConversationSubjectDialog() {
|
||||
val model = ConversationSetOrEditSubjectDialogModel("")
|
||||
val model = GroupSetOrEditSubjectDialogModel("", isGroupConversation = true)
|
||||
|
||||
val dialog = DialogUtils.getSetOrEditConversationSubjectDialog(
|
||||
val dialog = DialogUtils.getSetOrEditGroupSubjectDialog(
|
||||
requireContext(),
|
||||
model
|
||||
)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class StartConversationViewModel @UiThread constructor() : AddressSelectionViewM
|
|||
|
||||
val subject = MutableLiveData<String>()
|
||||
|
||||
val groupChatRoomCreateButtonEnabled = MediatorLiveData<Boolean>()
|
||||
val createGroupConversationButtonEnabled = MediatorLiveData<Boolean>()
|
||||
|
||||
val operationInProgress = MutableLiveData<Boolean>()
|
||||
|
||||
|
|
@ -87,9 +87,9 @@ class StartConversationViewModel @UiThread constructor() : AddressSelectionViewM
|
|||
}
|
||||
|
||||
init {
|
||||
groupChatRoomCreateButtonEnabled.postValue(false)
|
||||
groupChatRoomCreateButtonEnabled.addSource(selection) {
|
||||
groupChatRoomCreateButtonEnabled.postValue(it.isNotEmpty())
|
||||
createGroupConversationButtonEnabled.value = false
|
||||
createGroupConversationButtonEnabled.addSource(selection) {
|
||||
createGroupConversationButtonEnabled.value = it.isNotEmpty()
|
||||
}
|
||||
|
||||
updateGroupChatButtonVisibility()
|
||||
|
|
|
|||
|
|
@ -17,13 +17,16 @@
|
|||
* 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.chat.model
|
||||
package org.linphone.ui.main.fragment
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class ConversationSetOrEditSubjectDialogModel @UiThread constructor(initialSubject: String) {
|
||||
class GroupSetOrEditSubjectDialogModel @UiThread constructor(
|
||||
initialSubject: String,
|
||||
val isGroupConversation: Boolean
|
||||
) {
|
||||
val isEdit = initialSubject.isNotEmpty()
|
||||
|
||||
val subject = MutableLiveData<String>()
|
||||
|
|
@ -35,7 +35,9 @@ import org.linphone.core.Friend
|
|||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.StartCallFragmentBinding
|
||||
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.utils.DialogUtils
|
||||
import org.linphone.utils.addCharacterAtPosition
|
||||
import org.linphone.utils.hideKeyboard
|
||||
import org.linphone.utils.removeCharacterAtPosition
|
||||
|
|
@ -80,6 +82,11 @@ class StartCallFragment : GenericAddressPickerFragment() {
|
|||
viewModel.hideNumpad()
|
||||
}
|
||||
|
||||
binding.setAskForGroupCallSubjectClickListener {
|
||||
viewModel.hideNumpad()
|
||||
showGroupCallSubjectDialog()
|
||||
}
|
||||
|
||||
setupRecyclerView(binding.contactsAndSuggestionsList)
|
||||
|
||||
viewModel.contactsAndSuggestionsList.observe(
|
||||
|
|
@ -151,4 +158,40 @@ class StartCallFragment : GenericAddressPickerFragment() {
|
|||
|
||||
viewModel.isNumpadVisible.value = false
|
||||
}
|
||||
|
||||
private fun showGroupCallSubjectDialog() {
|
||||
val model = GroupSetOrEditSubjectDialogModel("", isGroupConversation = false)
|
||||
|
||||
val dialog = DialogUtils.getSetOrEditGroupSubjectDialog(
|
||||
requireContext(),
|
||||
model
|
||||
)
|
||||
|
||||
model.dismissEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
Log.i("$TAG Set group call subject cancelled")
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
model.confirmEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { newSubject ->
|
||||
if (newSubject.isNotEmpty()) {
|
||||
Log.i(
|
||||
"$TAG Group call subject has been set to [$newSubject]"
|
||||
)
|
||||
viewModel.subject.value = newSubject
|
||||
viewModel.createGroupCall()
|
||||
|
||||
dialog.currentFocus?.hideKeyboard()
|
||||
dialog.dismiss()
|
||||
} else {
|
||||
// TODO: show error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.i("$TAG Showing dialog to set group call subject")
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,12 +20,18 @@
|
|||
package org.linphone.ui.main.history.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.core.ConferenceScheduler
|
||||
import org.linphone.core.ConferenceSchedulerListenerStub
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.Participant
|
||||
import org.linphone.core.ParticipantInfo
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.history.model.NumpadModel
|
||||
import org.linphone.ui.main.viewmodel.AddressSelectionViewModel
|
||||
|
|
@ -45,7 +51,11 @@ class StartCallViewModel @UiThread constructor() : AddressSelectionViewModel() {
|
|||
|
||||
val isNumpadVisible = MutableLiveData<Boolean>()
|
||||
|
||||
val isGroupCallAvailable = MutableLiveData<Boolean>()
|
||||
val startGroupCallButtonEnabled = MediatorLiveData<Boolean>()
|
||||
|
||||
val subject = MutableLiveData<String>()
|
||||
|
||||
val operationInProgress = MutableLiveData<Boolean>()
|
||||
|
||||
val appendDigitToSearchBarEvent: MutableLiveData<Event<String>> by lazy {
|
||||
MutableLiveData<Event<String>>()
|
||||
|
|
@ -59,6 +69,35 @@ class StartCallViewModel @UiThread constructor() : AddressSelectionViewModel() {
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
private val conferenceSchedulerListener = object : ConferenceSchedulerListenerStub() {
|
||||
override fun onStateChanged(
|
||||
conferenceScheduler: ConferenceScheduler,
|
||||
state: ConferenceScheduler.State
|
||||
) {
|
||||
Log.i("$TAG Conference scheduler state is $state")
|
||||
if (state == ConferenceScheduler.State.Ready) {
|
||||
conferenceScheduler.removeListener(this)
|
||||
|
||||
val conferenceAddress = conferenceScheduler.info?.uri
|
||||
if (conferenceAddress != null) {
|
||||
Log.i(
|
||||
"$TAG Conference info created, address is ${conferenceAddress.asStringUriOnly()}"
|
||||
)
|
||||
coreContext.startCall(conferenceAddress)
|
||||
} else {
|
||||
Log.e("$TAG Conference info URI is null!")
|
||||
// TODO: notify error to user
|
||||
}
|
||||
operationInProgress.postValue(false)
|
||||
} else if (state == ConferenceScheduler.State.Error) {
|
||||
conferenceScheduler.removeListener(this)
|
||||
Log.e("$TAG Failed to create group call!")
|
||||
// TODO: notify error to user
|
||||
operationInProgress.postValue(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
isNumpadVisible.value = false
|
||||
numpadModel = NumpadModel(
|
||||
|
|
@ -89,6 +128,11 @@ class StartCallViewModel @UiThread constructor() : AddressSelectionViewModel() {
|
|||
}
|
||||
)
|
||||
|
||||
startGroupCallButtonEnabled.value = false
|
||||
startGroupCallButtonEnabled.addSource(selection) {
|
||||
startGroupCallButtonEnabled.value = it.isNotEmpty()
|
||||
}
|
||||
|
||||
updateGroupCallButtonVisibility()
|
||||
}
|
||||
|
||||
|
|
@ -116,4 +160,43 @@ class StartCallViewModel @UiThread constructor() : AddressSelectionViewModel() {
|
|||
fun hideNumpad() {
|
||||
isNumpadVisible.value = false
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun createGroupCall() {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
val account = core.defaultAccount
|
||||
if (account == null) {
|
||||
Log.e(
|
||||
"$TAG No default account found, can't create group call!"
|
||||
)
|
||||
return@postOnCoreThread
|
||||
}
|
||||
|
||||
operationInProgress.postValue(true)
|
||||
|
||||
val conferenceInfo = Factory.instance().createConferenceInfo()
|
||||
conferenceInfo.organizer = account.params.identityAddress
|
||||
conferenceInfo.subject = subject.value
|
||||
|
||||
val participants = arrayOfNulls<ParticipantInfo>(selection.value.orEmpty().size)
|
||||
var index = 0
|
||||
for (participant in selection.value.orEmpty()) {
|
||||
val info = Factory.instance().createParticipantInfo(participant.address)
|
||||
// For meetings, all participants must have Speaker role
|
||||
info?.role = Participant.Role.Speaker
|
||||
participants[index] = info
|
||||
index += 1
|
||||
}
|
||||
conferenceInfo.setParticipantInfos(participants)
|
||||
|
||||
Log.i(
|
||||
"$TAG Creating group call with subject ${subject.value} and ${participants.size} participant(s)"
|
||||
)
|
||||
val conferenceScheduler = core.createConferenceScheduler()
|
||||
conferenceScheduler.addListener(conferenceSchedulerListener)
|
||||
conferenceScheduler.account = account
|
||||
// Will trigger the conference creation/update automatically
|
||||
conferenceScheduler.info = conferenceInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,8 +76,7 @@ abstract class AddressSelectionViewModel @UiThread constructor() : DefaultAccoun
|
|||
applyFilter(
|
||||
currentFilter,
|
||||
if (limitSearchToLinphoneAccounts) corePreferences.defaultDomain else "",
|
||||
magicSearchSourceFlags,
|
||||
MagicSearch.Aggregation.Friend
|
||||
magicSearchSourceFlags
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +108,9 @@ abstract class AddressSelectionViewModel @UiThread constructor() : DefaultAccoun
|
|||
|
||||
@UiThread
|
||||
fun clearFilter() {
|
||||
searchFilter.value = ""
|
||||
if (searchFilter.value.orEmpty().isNotEmpty()) {
|
||||
searchFilter.value = ""
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
|
@ -185,8 +186,7 @@ abstract class AddressSelectionViewModel @UiThread constructor() : DefaultAccoun
|
|||
applyFilter(
|
||||
filter,
|
||||
if (limitSearchToLinphoneAccounts) corePreferences.defaultDomain else "",
|
||||
magicSearchSourceFlags,
|
||||
MagicSearch.Aggregation.Friend
|
||||
magicSearchSourceFlags
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -195,8 +195,7 @@ abstract class AddressSelectionViewModel @UiThread constructor() : DefaultAccoun
|
|||
private fun applyFilter(
|
||||
filter: String,
|
||||
domain: String,
|
||||
sources: Int,
|
||||
aggregation: MagicSearch.Aggregation
|
||||
sources: Int
|
||||
) {
|
||||
if (previousFilter.isNotEmpty() && (
|
||||
previousFilter.length > filter.length ||
|
||||
|
|
@ -215,7 +214,7 @@ abstract class AddressSelectionViewModel @UiThread constructor() : DefaultAccoun
|
|||
filter,
|
||||
domain,
|
||||
sources,
|
||||
aggregation
|
||||
MagicSearch.Aggregation.Friend
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,14 +44,14 @@ import org.linphone.databinding.DialogPickNumberOrAddressBinding
|
|||
import org.linphone.databinding.DialogRemoveAccountBinding
|
||||
import org.linphone.databinding.DialogRemoveAllCallLogsBinding
|
||||
import org.linphone.databinding.DialogRemoveCallLogsBinding
|
||||
import org.linphone.databinding.DialogSetOrEditGroupConversationSubjectBindingImpl
|
||||
import org.linphone.databinding.DialogSetOrEditGroupSubjectBindingImpl
|
||||
import org.linphone.databinding.DialogUpdateAvailableBinding
|
||||
import org.linphone.ui.assistant.model.AcceptConditionsAndPolicyDialogModel
|
||||
import org.linphone.ui.assistant.model.ConfirmPhoneNumberDialogModel
|
||||
import org.linphone.ui.call.model.ZrtpSasConfirmationDialogModel
|
||||
import org.linphone.ui.main.chat.model.ConversationSetOrEditSubjectDialogModel
|
||||
import org.linphone.ui.main.contacts.model.NumberOrAddressPickerDialogModel
|
||||
import org.linphone.ui.main.contacts.model.TrustCallDialogModel
|
||||
import org.linphone.ui.main.fragment.GroupSetOrEditSubjectDialogModel
|
||||
import org.linphone.ui.main.history.model.ConfirmationDialogModel
|
||||
|
||||
class DialogUtils {
|
||||
|
|
@ -268,13 +268,13 @@ class DialogUtils {
|
|||
}
|
||||
|
||||
@UiThread
|
||||
fun getSetOrEditConversationSubjectDialog(
|
||||
fun getSetOrEditGroupSubjectDialog(
|
||||
context: Context,
|
||||
viewModel: ConversationSetOrEditSubjectDialogModel
|
||||
viewModel: GroupSetOrEditSubjectDialogModel
|
||||
): Dialog {
|
||||
val binding: DialogSetOrEditGroupConversationSubjectBindingImpl = DataBindingUtil.inflate(
|
||||
val binding: DialogSetOrEditGroupSubjectBindingImpl = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(context),
|
||||
R.layout.dialog_set_or_edit_group_conversation_subject,
|
||||
R.layout.dialog_set_or_edit_group_subject,
|
||||
null,
|
||||
false
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<import type="android.graphics.Typeface" />
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="org.linphone.ui.main.chat.model.ConversationSetOrEditSubjectDialogModel" />
|
||||
type="org.linphone.ui.main.fragment.GroupSetOrEditSubjectDialogModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:paddingTop="@dimen/dialog_top_bottom_margin"
|
||||
android:text="@{viewModel.isEdit ? @string/dialog_group_conversation_edit_subject : @string/dialog_group_conversation_set_subject, default=@string/dialog_group_conversation_set_subject}"
|
||||
android:text="@{viewModel.isGroupConversation ? viewModel.isEdit ? @string/dialog_group_conversation_edit_subject : @string/dialog_group_conversation_set_subject : @string/dialog_group_call_set_subject, default=@string/dialog_group_conversation_set_subject}"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintBottom_toTopOf="@id/subject"
|
||||
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
android:layout_marginTop="5dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:hint="@string/dialog_group_conversation_subject_hint"
|
||||
android:hint="@{viewModel.isGroupConversation ? @string/dialog_group_conversation_subject_hint : @string/dialog_group_call_subject_hint, default=@string/dialog_group_conversation_subject_hint}"
|
||||
android:text="@={viewModel.subject, default=`Lorem Ipsum`}"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?attr/color_main2_600"
|
||||
|
|
@ -109,8 +109,9 @@
|
|||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:src="@{model.wasConference ? @drawable/meeting : @drawable/phone, default=@drawable/phone}"
|
||||
android:src="@drawable/phone"
|
||||
app:tint="?attr/color_main2_500"
|
||||
android:visibility="@{model.wasConference ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/name"
|
||||
app:layout_constraintBottom_toBottomOf="@id/date_time" />
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
<variable
|
||||
name="hideNumpadClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="askForGroupCallSubjectClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="org.linphone.ui.main.history.viewmodel.StartCallViewModel" />
|
||||
|
|
@ -25,27 +28,34 @@
|
|||
android:layout_height="match_parent"
|
||||
android:background="?attr/color_main2_000">
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/multiple_selection_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="multiple_selection, multiple_selection_count"
|
||||
android:visibility="@{viewModel.multipleSelectionMode ? View.VISIBLE : View.GONE, default=gone}" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:adjustViewBounds="true"
|
||||
android:onClick="@{backClickListener}"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="?attr/color_main1_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/main_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@{viewModel.title, default=@string/history_call_start_title}"
|
||||
app:layout_constraintBottom_toBottomOf="@id/back"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/back"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
|
@ -57,15 +67,44 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/back" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/multiple_selection_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{viewModel.selectionCount, default=`0 selected`}"
|
||||
android:textSize="12sp"
|
||||
android:textColor="?attr/color_main2_900"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/multiple_selection"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/multiple_selection_count">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
entries="@{viewModel.selection}"
|
||||
layout="@{@layout/address_selected_list_cell}"/>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
style="@style/default_text_style"
|
||||
android:id="@+id/search_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:background="@drawable/edit_text_background"
|
||||
android:drawableStart="@drawable/magnifying_glass"
|
||||
|
|
@ -83,7 +122,7 @@
|
|||
app:layout_constraintWidth_max="@dimen/text_input_max_width"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||
app:layout_constraintTop_toBottomOf="@id/multiple_selection" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/numpad"
|
||||
|
|
@ -116,7 +155,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="group_call_icon, gradient_background, group_call_label"
|
||||
android:visibility="@{viewModel.hideGroupCallButton || viewModel.searchFilter.length() > 0 ? View.GONE : View.VISIBLE}" />
|
||||
android:visibility="@{viewModel.hideGroupCallButton || viewModel.multipleSelectionMode || viewModel.searchFilter.length() > 0 ? View.GONE : View.VISIBLE}" />
|
||||
|
||||
<!-- margin start must be half the size of the group_call_icon below -->
|
||||
<View
|
||||
|
|
@ -132,6 +171,7 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/group_call_icon"
|
||||
android:onClick="@{() -> viewModel.switchToMultipleSelectionMode()}"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginStart="16dp"
|
||||
|
|
@ -146,6 +186,7 @@
|
|||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_800"
|
||||
android:id="@+id/group_call_label"
|
||||
android:onClick="@{() -> viewModel.switchToMultipleSelectionMode()}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
|
|
@ -198,6 +239,21 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/group_call_icon"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/create_group"
|
||||
android:onClick="@{askForGroupCallSubjectClickListener}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_margin="16dp"
|
||||
android:visibility="@{viewModel.multipleSelectionMode && viewModel.startGroupCallButtonEnabled ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:src="@drawable/check"
|
||||
app:tint="?attr/color_on_main"
|
||||
app:backgroundTint="?attr/color_main1_500"
|
||||
app:shapeAppearanceOverlay="@style/rounded"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<include
|
||||
|
|
@ -206,6 +262,10 @@
|
|||
bind:model="@{viewModel.numpadModel}"
|
||||
layout="@layout/start_call_numpad_bottom_sheet" />
|
||||
|
||||
<include
|
||||
layout="@layout/operation_in_progress"
|
||||
bind:visibility="@{viewModel.operationInProgress}" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</layout>
|
||||
|
|
@ -229,7 +229,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_margin="16dp"
|
||||
android:visibility="@{viewModel.multipleSelectionMode && viewModel.groupChatRoomCreateButtonEnabled ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{viewModel.multipleSelectionMode && viewModel.createGroupConversationButtonEnabled ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:src="@drawable/check"
|
||||
app:tint="?attr/color_on_main"
|
||||
app:backgroundTint="?attr/color_main1_500"
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@
|
|||
<string name="dialog_group_conversation_edit_subject">Edit conversation subject</string>
|
||||
<string name="dialog_group_conversation_subject_hint">Conversation subject</string>
|
||||
<string name="dialog_group_conversation_edit_subject_confirm_button">Confirm</string>
|
||||
<string name="dialog_group_call_set_subject">Set group call subject</string>
|
||||
<string name="dialog_group_call_subject_hint">Group call subject</string>
|
||||
|
||||
<string name="toast_assistant_qr_code_invalid">Invalid QR code!</string>
|
||||
<string name="toast_sip_address_copied_to_clipboard">SIP address copied into clipboard</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue