mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Added search in conversation top bar
This commit is contained in:
parent
a2355e3225
commit
f9d2e04609
15 changed files with 250 additions and 81 deletions
|
|
@ -152,7 +152,9 @@ class ConversationEventAdapter(
|
|||
return if (!oldItem.isEvent && !newItem.isEvent) {
|
||||
val oldData = (oldItem.model as ChatMessageModel)
|
||||
val newData = (newItem.model as ChatMessageModel)
|
||||
oldData.time == newData.time && oldData.isOutgoing == newData.isOutgoing
|
||||
oldData.id == newData.id &&
|
||||
oldData.timestamp == newData.timestamp &&
|
||||
oldData.isOutgoing == newData.isOutgoing
|
||||
} else {
|
||||
oldItem.notifyId == newItem.notifyId
|
||||
}
|
||||
|
|
@ -162,8 +164,8 @@ class ConversationEventAdapter(
|
|||
return if (oldItem.isEvent && newItem.isEvent) {
|
||||
true
|
||||
} else if (!oldItem.isEvent && !newItem.isEvent) {
|
||||
val oldModel = (newItem.model as ChatMessageModel)
|
||||
val newModel = newItem.model
|
||||
val oldModel = (oldItem.model as ChatMessageModel)
|
||||
val newModel = (newItem.model as ChatMessageModel)
|
||||
oldModel.statusIcon.value == newModel.statusIcon.value
|
||||
} else {
|
||||
false
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ import org.linphone.ui.main.chat.viewmodel.ConversationViewModel
|
|||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.hideKeyboard
|
||||
import org.linphone.utils.showKeyboard
|
||||
|
||||
@UiThread
|
||||
class ConversationFragment : GenericFragment() {
|
||||
|
|
@ -176,6 +178,21 @@ class ConversationFragment : GenericFragment() {
|
|||
)
|
||||
findNavController().navigate(action)
|
||||
}
|
||||
|
||||
viewModel.searchFilter.observe(viewLifecycleOwner) { filter ->
|
||||
viewModel.applyFilter(filter.trim())
|
||||
}
|
||||
|
||||
viewModel.focusSearchBarEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { show ->
|
||||
if (show) {
|
||||
// To automatically open keyboard
|
||||
binding.search.showKeyboard()
|
||||
} else {
|
||||
binding.search.hideKeyboard()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showChatMessageLongPressMenu(chatMessageModel: ChatMessageModel) {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,9 @@ class ChatMessageModel @WorkerThread constructor(
|
|||
|
||||
val text = LinphoneUtils.getTextDescribingMessage(chatMessage)
|
||||
|
||||
val time = TimestampUtils.toString(chatMessage.time)
|
||||
val timestamp = chatMessage.time
|
||||
|
||||
val time = TimestampUtils.toString(timestamp)
|
||||
|
||||
val chatRoomIsReadOnly = chatMessage.chatRoom.isReadOnly
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,5 @@ package org.linphone.ui.main.chat.model
|
|||
import org.linphone.core.Friend
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
|
||||
class ParticipantModel(friend: Friend, val isMyselfAdmin: Boolean, val isParticipantAdmin: Boolean) : ContactAvatarModel(
|
||||
friend
|
||||
)
|
||||
class ParticipantModel(friend: Friend, val isMyselfAdmin: Boolean, val isParticipantAdmin: Boolean) :
|
||||
ContactAvatarModel(friend)
|
||||
|
|
|
|||
|
|
@ -70,17 +70,17 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
|
|||
private val chatRoomListener = object : ChatRoomListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onParticipantAdded(chatRoom: ChatRoom, eventLog: EventLog) {
|
||||
computeParticipantsList(isGroup.value == true)
|
||||
computeParticipantsList()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onParticipantRemoved(chatRoom: ChatRoom, eventLog: EventLog) {
|
||||
computeParticipantsList(isGroup.value == true)
|
||||
computeParticipantsList()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onParticipantAdminStatusChanged(chatRoom: ChatRoom, eventLog: EventLog) {
|
||||
computeParticipantsList(isGroup.value == true)
|
||||
computeParticipantsList()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
|
@ -183,8 +183,7 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
isMyselfAdmin.postValue(chatRoom.me?.isAdmin)
|
||||
|
||||
val isGroupChatRoom = !chatRoom.hasCapability(ChatRoom.Capabilities.OneToOne.toInt()) &&
|
||||
chatRoom.hasCapability(ChatRoom.Capabilities.Conference.toInt())
|
||||
val isGroupChatRoom = isChatRoomAGroup()
|
||||
isGroup.postValue(isGroupChatRoom)
|
||||
|
||||
val empty = chatRoom.hasCapability(ChatRoom.Capabilities.Conference.toInt()) && chatRoom.participants.isEmpty()
|
||||
|
|
@ -196,14 +195,16 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
subject.postValue(chatRoom.subject)
|
||||
|
||||
computeParticipantsList(isGroupChatRoom)
|
||||
computeParticipantsList()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun computeParticipantsList(isGroupChatRoom: Boolean) {
|
||||
private fun computeParticipantsList() {
|
||||
avatarModel.value?.destroy()
|
||||
avatarsMap.values.forEach(ParticipantModel::destroy)
|
||||
|
||||
val groupChatRoom = isChatRoomAGroup()
|
||||
|
||||
val friends = arrayListOf<Friend>()
|
||||
val participantsList = arrayListOf<ParticipantModel>()
|
||||
if (chatRoom.hasCapability(ChatRoom.Capabilities.Basic.toInt())) {
|
||||
|
|
@ -214,14 +215,14 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
|
|||
for (participant in chatRoom.participants) {
|
||||
val model = getParticipantModelForAddress(
|
||||
participant.address,
|
||||
if (isGroup.value == true) participant.isAdmin else false
|
||||
if (groupChatRoom) participant.isAdmin else false
|
||||
)
|
||||
friends.add(model.friend)
|
||||
participantsList.add(model)
|
||||
}
|
||||
}
|
||||
|
||||
val avatar = if (isGroupChatRoom) {
|
||||
val avatar = if (groupChatRoom) {
|
||||
val fakeFriend = coreContext.core.createFriend()
|
||||
ContactAvatarModel(fakeFriend)
|
||||
} else {
|
||||
|
|
@ -260,4 +261,13 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
|
|||
avatarsMap[key] = avatar
|
||||
return avatar
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun isChatRoomAGroup(): Boolean {
|
||||
return if (::chatRoom.isInitialized) {
|
||||
LinphoneUtils.isChatRoomAGroup(chatRoom)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,10 +62,20 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val textToSend = MutableLiveData<String>()
|
||||
|
||||
val searchBarVisible = MutableLiveData<Boolean>()
|
||||
|
||||
val searchFilter = MutableLiveData<String>()
|
||||
|
||||
val focusSearchBarEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val chatRoomFoundEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
private lateinit var chatRoom: ChatRoom
|
||||
|
||||
private var currentFilter = ""
|
||||
|
||||
private val avatarsMap = hashMapOf<String, ContactAvatarModel>()
|
||||
|
||||
private val chatRoomListener = object : ChatRoomListenerStub() {
|
||||
|
|
@ -84,7 +94,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
} else {
|
||||
false
|
||||
}
|
||||
list.add(EventLogModel(eventLog, avatarModel, isGroup.value == true, group, true))
|
||||
list.add(EventLogModel(eventLog, avatarModel, isChatRoomAGroup(), group, true))
|
||||
|
||||
events.postValue(list)
|
||||
}
|
||||
|
|
@ -118,7 +128,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val newList = getEventsListFromHistory(
|
||||
eventLogs,
|
||||
isGroupChatRoom = isGroup.value == true
|
||||
searchFilter.value.orEmpty().trim()
|
||||
)
|
||||
list.addAll(newList)
|
||||
|
||||
|
|
@ -128,6 +138,10 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
init {
|
||||
searchBarVisible.value = false
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
|
|
@ -139,6 +153,24 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun openSearchBar() {
|
||||
searchBarVisible.value = true
|
||||
focusSearchBarEvent.value = Event(true)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun closeSearchBar() {
|
||||
clearFilter()
|
||||
searchBarVisible.value = false
|
||||
focusSearchBarEvent.value = Event(false)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun clearFilter() {
|
||||
searchFilter.value = ""
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun findChatRoom(localSipUri: String, remoteSipUri: String) {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
|
|
@ -174,6 +206,13 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun applyFilter(filter: String) {
|
||||
coreContext.postOnCoreThread {
|
||||
computeEvents(filter)
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun sendMessage() {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
|
|
@ -215,10 +254,6 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
private fun configureChatRoom() {
|
||||
computeComposingLabel()
|
||||
|
||||
val isGroupChatRoom = !chatRoom.hasCapability(ChatRoom.Capabilities.OneToOne.toInt()) &&
|
||||
chatRoom.hasCapability(ChatRoom.Capabilities.Conference.toInt())
|
||||
isGroup.postValue(isGroupChatRoom)
|
||||
|
||||
val empty = chatRoom.hasCapability(ChatRoom.Capabilities.Conference.toInt()) && chatRoom.participants.isEmpty()
|
||||
val readOnly = chatRoom.isReadOnly || empty
|
||||
isReadOnly.postValue(readOnly)
|
||||
|
|
@ -226,6 +261,9 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
Log.w("$TAG Chat room with subject [${chatRoom.subject}] is read only!")
|
||||
}
|
||||
|
||||
val group = isChatRoomAGroup()
|
||||
isGroup.postValue(group)
|
||||
|
||||
subject.postValue(chatRoom.subject)
|
||||
|
||||
val friends = arrayListOf<Friend>()
|
||||
|
|
@ -243,7 +281,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
firstParticipant?.address ?: chatRoom.peerAddress
|
||||
}
|
||||
|
||||
val avatar = if (isGroupChatRoom) {
|
||||
val avatar = if (group) {
|
||||
val fakeFriend = coreContext.core.createFriend()
|
||||
ContactAvatarModel(fakeFriend)
|
||||
} else {
|
||||
|
|
@ -252,17 +290,22 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
avatar.setPicturesFromFriends(friends)
|
||||
avatarModel.postValue(avatar)
|
||||
|
||||
val history = chatRoom.getHistoryEvents(0)
|
||||
val eventsList = getEventsListFromHistory(history, isGroupChatRoom)
|
||||
|
||||
events.postValue(eventsList)
|
||||
computeEvents()
|
||||
chatRoom.markAsRead()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun computeEvents(filter: String = "") {
|
||||
events.value.orEmpty().forEach(EventLogModel::destroy)
|
||||
|
||||
val history = chatRoom.getHistoryEvents(0)
|
||||
val eventsList = getEventsListFromHistory(history, filter)
|
||||
events.postValue(eventsList)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun processGroupedEvents(
|
||||
groupedEventLogs: ArrayList<EventLog>,
|
||||
isGroupChatRoom: Boolean
|
||||
groupedEventLogs: ArrayList<EventLog>
|
||||
): ArrayList<EventLogModel> {
|
||||
val eventsList = arrayListOf<EventLogModel>()
|
||||
|
||||
|
|
@ -273,7 +316,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
val model = EventLogModel(
|
||||
groupedEvent,
|
||||
avatar,
|
||||
isGroupChatRoom,
|
||||
isChatRoomAGroup(),
|
||||
index > 0,
|
||||
index == groupedEventLogs.size - 1
|
||||
)
|
||||
|
|
@ -286,10 +329,26 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getEventsListFromHistory(history: Array<EventLog>, isGroupChatRoom: Boolean): ArrayList<EventLogModel> {
|
||||
private fun getEventsListFromHistory(history: Array<EventLog>, filter: String = ""): ArrayList<EventLogModel> {
|
||||
val eventsList = arrayListOf<EventLogModel>()
|
||||
val groupedEventLogs = arrayListOf<EventLog>()
|
||||
for (event in history) {
|
||||
// TODO: let the SDK do it
|
||||
if (event.type == EventLog.Type.ConferenceChatMessage) {
|
||||
val message = event.chatMessage ?: continue
|
||||
val fromAddress = message.fromAddress
|
||||
val model = getAvatarModelForAddress(fromAddress)
|
||||
if (
|
||||
!model.name.value.orEmpty().contains(filter, ignoreCase = true) &&
|
||||
!fromAddress.asStringUriOnly().contains(filter, ignoreCase = true) &&
|
||||
!message.utf8Text.orEmpty().contains(filter, ignoreCase = true)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
if (groupedEventLogs.isEmpty()) {
|
||||
groupedEventLogs.add(event)
|
||||
continue
|
||||
|
|
@ -299,7 +358,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
val groupEvents = shouldWeGroupTwoEvents(event, previousGroupEvent)
|
||||
|
||||
if (!groupEvents) {
|
||||
eventsList.addAll(processGroupedEvents(groupedEventLogs, isGroupChatRoom))
|
||||
eventsList.addAll(processGroupedEvents(groupedEventLogs))
|
||||
groupedEventLogs.clear()
|
||||
}
|
||||
|
||||
|
|
@ -307,7 +366,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
|
||||
if (groupedEventLogs.isNotEmpty()) {
|
||||
eventsList.addAll(processGroupedEvents(groupedEventLogs, isGroupChatRoom))
|
||||
eventsList.addAll(processGroupedEvents(groupedEventLogs))
|
||||
groupedEventLogs.clear()
|
||||
}
|
||||
|
||||
|
|
@ -380,4 +439,13 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
composingLabel.postValue("")
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun isChatRoomAGroup(): Boolean {
|
||||
return if (::chatRoom.isInitialized) {
|
||||
LinphoneUtils.isChatRoomAGroup(chatRoom)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,6 +199,12 @@ class LinphoneUtils {
|
|||
return "${localSipUri.asStringUriOnly()}~${remoteSipUri.asStringUriOnly()}"
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun isChatRoomAGroup(chatRoom: ChatRoom): Boolean {
|
||||
return !chatRoom.hasCapability(ChatRoom.Capabilities.OneToOne.toInt()) &&
|
||||
chatRoom.hasCapability(ChatRoom.Capabilities.Conference.toInt())
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getRecordingFilePathForAddress(address: Address): String {
|
||||
val displayName = getDisplayName(address)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<corners android:topRightRadius="16dp" android:bottomRightRadius="16dp" android:bottomLeftRadius="16dp" />
|
||||
<solid android:color="@color/gray_100"/>
|
||||
<solid android:color="@color/white"/>
|
||||
</shape>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<corners android:radius="16dp" />
|
||||
<solid android:color="@color/gray_100"/>
|
||||
<solid android:color="@color/white"/>
|
||||
</shape>
|
||||
|
|
@ -64,12 +64,12 @@
|
|||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<org.linphone.ui.main.chat.view.ChatBubbleTextView
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style"
|
||||
android:id="@+id/text_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginStart="26dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:paddingBottom="@{model.groupedWithNextOne ? @dimen/chat_bubble_text_padding_with_status : @dimen/chat_bubble_text_padding_with_bubble, default=@dimen/chat_bubble_text_padding_with_status}"
|
||||
|
|
@ -104,7 +104,6 @@
|
|||
android:layout_width="@dimen/small_icon_size"
|
||||
android:layout_height="@dimen/small_icon_size"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:src="@{model.statusIcon, default=@drawable/checks}"
|
||||
android:visibility="@{model.isGroupedWithNextOne ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintTop_toTopOf="@id/date_time"
|
||||
|
|
|
|||
|
|
@ -36,6 +36,25 @@
|
|||
android:layout_marginBottom="80dp"
|
||||
android:background="@color/white">
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="avatar, title, search_toggle, info"
|
||||
android:visibility="@{viewModel.searchBarVisible ? View.GONE : View.VISIBLE}" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="cancel_search, search, clear_field"
|
||||
android:visibility="@{viewModel.searchBarVisible ? View.VISIBLE : View.GONE, default=gone}" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/top_bar_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="title, search" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -43,7 +62,7 @@
|
|||
android:padding="15dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:onClick="@{backClickListener}"
|
||||
android:visibility="@{viewModel.showBackButton ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{viewModel.showBackButton && !viewModel.searchBarVisible ? View.VISIBLE : View.GONE}"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
|
|
@ -68,7 +87,7 @@
|
|||
android:layout_width="@dimen/avatar_presence_badge_size"
|
||||
android:layout_height="@dimen/avatar_presence_badge_size"
|
||||
android:src="@{viewModel.avatarModel.trust == SecurityLevel.Safe ? @drawable/trusted : @drawable/not_trusted, default=@drawable/trusted}"
|
||||
android:visibility="@{viewModel.avatarModel.trust == SecurityLevel.Safe || viewModel.avatarModel.trust == SecurityLevel.Unsafe ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{!viewModel.searchBarVisible && (viewModel.avatarModel.trust == SecurityLevel.Safe || viewModel.avatarModel.trust == SecurityLevel.Unsafe) ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||
|
||||
|
|
@ -78,14 +97,14 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:text="@{viewModel.isGroup ? viewModel.subject : viewModel.avatarModel.name, default=`John Doe`}"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/gray_main2_600"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintEnd_toStartOf="@id/call"
|
||||
app:layout_constraintEnd_toStartOf="@id/search_toggle"
|
||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
|
|
@ -99,38 +118,82 @@
|
|||
android:src="@drawable/info"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:tint="@color/gray_main2_500"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/video_call"
|
||||
android:onClick="@{startVideoCallClickListener}"
|
||||
android:id="@+id/search_toggle"
|
||||
android:onClick="@{() -> viewModel.openSearchBar()}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:padding="15dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/video_camera"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
android:src="@drawable/magnifying_glass"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintEnd_toStartOf="@id/info" />
|
||||
app:layout_constraintEnd_toStartOf="@id/info"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:tint="@color/gray_main2_500" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/call"
|
||||
android:onClick="@{startCallClickListener}"
|
||||
android:id="@+id/cancel_search"
|
||||
android:onClick="@{() -> viewModel.closeSearchBar()}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:padding="15dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/phone"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintEnd_toStartOf="@id/video_call"/>
|
||||
android:src="@drawable/caret_left"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/search"
|
||||
app:tint="@color/gray_main2_500" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="?attr/textInputFilledStyle"
|
||||
android:id="@+id/search"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:gravity="center_vertical"
|
||||
android:textColorHint="@color/gray_main2_400"
|
||||
app:hintEnabled="false"
|
||||
app:hintAnimationEnabled="false"
|
||||
app:hintTextColor="@color/gray_main2_400"
|
||||
app:boxStrokeWidth="0dp"
|
||||
app:boxStrokeWidthFocused="0dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/clear_field"
|
||||
app:layout_constraintStart_toEndOf="@id/cancel_search"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:textCursorDrawable="@null"
|
||||
android:textSize="16sp"
|
||||
android:inputType="text"
|
||||
android:paddingVertical="1dp"
|
||||
android:text="@={viewModel.searchFilter}"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/clear_field"
|
||||
android:onClick="@{() -> viewModel.clearFilter()}"
|
||||
android:enabled="@{viewModel.searchFilter.length() > 0}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="9dp"
|
||||
android:src="@drawable/x"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/search"
|
||||
app:tint="@color/gray_main2_500" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/events_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
android:paddingBottom="5dp"
|
||||
android:background="@color/gray_100"
|
||||
app:layout_constraintTop_toBottomOf="@id/top_bar_barrier"
|
||||
app:layout_constraintBottom_toTopOf="@id/composing" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
|
|
@ -139,7 +202,8 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:background="@color/gray_100"
|
||||
android:text="@{viewModel.composingLabel, default=`John Doe is composing...`}"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/gray_main2_400"
|
||||
|
|
|
|||
|
|
@ -55,11 +55,11 @@
|
|||
android:id="@+id/thumbs_up"
|
||||
android:onClick="@{() -> model.sendReaction(@string/emoji_thumbs_up)}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/emoji_thumbs_up"
|
||||
android:textSize="30sp"
|
||||
android:textSize="@dimen/chat_bubble_long_press_emoji_reaction_size"
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintTop_toTopOf="@id/emojis_background"
|
||||
app:layout_constraintBottom_toBottomOf="@id/emojis_background"
|
||||
|
|
@ -71,12 +71,13 @@
|
|||
android:id="@+id/love"
|
||||
android:onClick="@{() -> model.sendReaction(@string/emoji_love)}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/emoji_love"
|
||||
android:textSize="30sp"
|
||||
android:textSize="@dimen/chat_bubble_long_press_emoji_reaction_size"
|
||||
app:layout_constraintTop_toTopOf="@id/thumbs_up"
|
||||
app:layout_constraintBottom_toBottomOf="@id/emojis_background"
|
||||
app:layout_constraintStart_toEndOf="@id/thumbs_up"
|
||||
app:layout_constraintEnd_toStartOf="@id/laughing"/>
|
||||
|
||||
|
|
@ -85,12 +86,13 @@
|
|||
android:id="@+id/laughing"
|
||||
android:onClick="@{() -> model.sendReaction(@string/emoji_laughing)}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/emoji_laughing"
|
||||
android:textSize="30sp"
|
||||
android:textSize="@dimen/chat_bubble_long_press_emoji_reaction_size"
|
||||
app:layout_constraintTop_toTopOf="@id/thumbs_up"
|
||||
app:layout_constraintBottom_toBottomOf="@id/emojis_background"
|
||||
app:layout_constraintStart_toEndOf="@id/love"
|
||||
app:layout_constraintEnd_toStartOf="@id/surprised"/>
|
||||
|
||||
|
|
@ -99,12 +101,13 @@
|
|||
android:id="@+id/surprised"
|
||||
android:onClick="@{() -> model.sendReaction(@string/emoji_surprised)}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/emoji_surprised"
|
||||
android:textSize="30sp"
|
||||
android:textSize="@dimen/chat_bubble_long_press_emoji_reaction_size"
|
||||
app:layout_constraintTop_toTopOf="@id/thumbs_up"
|
||||
app:layout_constraintBottom_toBottomOf="@id/emojis_background"
|
||||
app:layout_constraintStart_toEndOf="@id/laughing"
|
||||
app:layout_constraintEnd_toStartOf="@id/tear"/>
|
||||
|
||||
|
|
@ -113,12 +116,13 @@
|
|||
android:id="@+id/tear"
|
||||
android:onClick="@{() -> model.sendReaction(@string/emoji_tear)}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/emoji_tear"
|
||||
android:textSize="30sp"
|
||||
android:textSize="@dimen/chat_bubble_long_press_emoji_reaction_size"
|
||||
app:layout_constraintTop_toTopOf="@id/thumbs_up"
|
||||
app:layout_constraintBottom_toBottomOf="@id/emojis_background"
|
||||
app:layout_constraintStart_toEndOf="@id/surprised"
|
||||
app:layout_constraintEnd_toStartOf="@id/plus"/>
|
||||
|
||||
|
|
@ -133,7 +137,7 @@
|
|||
app:layout_constraintStart_toEndOf="@id/tear"
|
||||
app:layout_constraintEnd_toEndOf="@id/emojis_background"
|
||||
app:layout_constraintTop_toTopOf="@id/thumbs_up"
|
||||
app:layout_constraintBottom_toBottomOf="@id/thumbs_up" />
|
||||
app:layout_constraintBottom_toBottomOf="@id/emojis_background" />
|
||||
|
||||
<include
|
||||
android:id="@+id/bubble"
|
||||
|
|
|
|||
|
|
@ -74,9 +74,8 @@
|
|||
android:id="@+id/search_toggle"
|
||||
android:onClick="@{() -> viewModel.openSearchBar()}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="9dp"
|
||||
android:layout_height="0dp"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/magnifying_glass"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
@ -87,9 +86,8 @@
|
|||
android:id="@+id/cancel_search"
|
||||
android:onClick="@{() -> viewModel.closeSearchBar()}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_height="0dp"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
@ -130,9 +128,8 @@
|
|||
android:onClick="@{() -> viewModel.clearFilter()}"
|
||||
android:enabled="@{viewModel.searchFilter.length() > 0}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp"
|
||||
android:layout_marginEnd="9dp"
|
||||
android:layout_height="0dp"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/x"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<dimen name="call_all_actions_menu_height">235dp</dimen> <!-- sum of above two -->
|
||||
|
||||
<dimen name="landscape_nav_bar_width">75dp</dimen>
|
||||
<dimen name="sliding_pane_left_fragment_width">325dp</dimen>
|
||||
<dimen name="sliding_pane_left_fragment_width">425dp</dimen>
|
||||
<!-- This value is the result of the above two added together -->
|
||||
<dimen name="sliding_pane_left_fragment_with_nav_width">400dp</dimen>
|
||||
<dimen name="sliding_pane_left_fragment_with_nav_width">500dp</dimen>
|
||||
</resources>
|
||||
|
|
@ -65,4 +65,5 @@
|
|||
<dimen name="chat_bubble_long_press_menu_bubble_offset">110dp</dimen>
|
||||
<dimen name="chat_bubble_text_padding_with_bubble">12dp</dimen>
|
||||
<dimen name="chat_bubble_text_padding_with_status">5dp</dimen>
|
||||
<dimen name="chat_bubble_long_press_emoji_reaction_size">30sp</dimen>
|
||||
</resources>
|
||||
Loading…
Add table
Reference in a new issue