Various UI improvements

This commit is contained in:
Sylvain Berfini 2023-11-08 11:30:46 +01:00
parent 76b41b693b
commit cd3b9e1422
14 changed files with 127 additions and 53 deletions

View file

@ -278,6 +278,13 @@ class ConversationFragment : GenericFragment() {
}
}
viewModel.conferenceToJoinEvent.observe(viewLifecycleOwner) {
it.consume { conferenceUri ->
Log.i("$TAG Requesting to go to waiting room for conference URI [$conferenceUri]")
sharedViewModel.goToMeetingWaitingRoomEvent.value = Event(conferenceUri)
}
}
binding.root.setKeyboardInsetListener { keyboardVisible ->
if (keyboardVisible) {
viewModel.isEmojiPickerOpen.value = false

View file

@ -55,7 +55,10 @@ class ConversationsFragment : GenericFragment() {
}
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
if (findNavController().currentDestination?.id == R.id.startConversationFragment) {
if (
findNavController().currentDestination?.id == R.id.startConversationFragment ||
findNavController().currentDestination?.id == R.id.meetingWaitingRoomFragment
) {
// Holds fragment in place while new contact fragment slides over it
return AnimationUtils.loadAnimation(activity, R.anim.hold)
}
@ -115,9 +118,12 @@ class ConversationsFragment : GenericFragment() {
sharedViewModel.showStartConversationEvent.observe(viewLifecycleOwner) {
it.consume {
Log.i("$TAG Navigating to start conversation fragment")
val action = ConversationsFragmentDirections.actionConversationsFragmentToStartConversationFragment()
findNavController().navigate(action)
if (findNavController().currentDestination?.id == R.id.conversationsFragment) {
Log.i("$TAG Navigating to start conversation fragment")
val action =
ConversationsFragmentDirections.actionConversationsFragmentToStartConversationFragment()
findNavController().navigate(action)
}
}
}
@ -136,6 +142,19 @@ class ConversationsFragment : GenericFragment() {
}
}
sharedViewModel.goToMeetingWaitingRoomEvent.observe(viewLifecycleOwner) {
it.consume { uri ->
if (findNavController().currentDestination?.id == R.id.conversationsFragment) {
Log.i("$TAG Navigating to meeting waiting room fragment with URI [$uri]")
val action =
ConversationsFragmentDirections.actionConversationsFragmentToMeetingWaitingRoomFragment(
uri
)
findNavController().navigate(action)
}
}
}
sharedViewModel.navigateToContactsEvent.observe(viewLifecycleOwner) {
it.consume {
if (findNavController().currentDestination?.id == R.id.conversationsFragment) {

View file

@ -52,7 +52,8 @@ class ChatMessageModel @WorkerThread constructor(
val replyToMessageId: String?,
val isGroupedWithPreviousOne: Boolean,
val isGroupedWithNextOne: Boolean,
val onContentClicked: ((file: String) -> Unit)? = null
private val onContentClicked: ((file: String) -> Unit)? = null,
private val onJoinConferenceClicked: ((uri: String) -> Unit)? = null
) {
companion object {
private const val TAG = "[Chat Message Model]"
@ -207,8 +208,12 @@ class ChatMessageModel @WorkerThread constructor(
fun joinConference() {
coreContext.postOnCoreThread {
if (::meetingConferenceUri.isInitialized) {
Log.i("$TAG Calling conference URI [${meetingConferenceUri.asStringUriOnly()}]")
coreContext.startCall(meetingConferenceUri)
val uri = meetingConferenceUri.asStringUriOnly()
coreContext.postOnMainThread {
onJoinConferenceClicked?.invoke(uri)
}
/*Log.i("$TAG Calling conference URI [${meetingConferenceUri.asStringUriOnly()}]")
coreContext.startCall(meetingConferenceUri)*/
}
}
}
@ -347,9 +352,12 @@ class ChatMessageModel @WorkerThread constructor(
meetingDay.postValue(TimestampUtils.dayOfWeek(timestamp))
meetingDayNumber.postValue(TimestampUtils.dayOfMonth(timestamp))
// TODO: fixme
var count = 0
for (info in conferenceInfo.participantInfos) {
count += 1
}
meetingParticipants.postValue(
AppUtils.getFormattedString(R.string.conference_participants_list_title, "24")
AppUtils.getFormattedString(R.string.conference_participants_list_title, "$count")
)
meetingFound.postValue(true)

View file

@ -222,10 +222,22 @@ class ConversationModel @WorkerThread constructor(val chatRoom: ChatRoom) {
@WorkerThread
private fun updateLastMessageStatus(message: ChatMessage) {
val text = LinphoneUtils.getTextDescribingMessage(message)
lastMessageText.postValue(text)
val isOutgoing = message.isOutgoing
val text = LinphoneUtils.getTextDescribingMessage(message)
if (isGroup && !isOutgoing) {
val fromAddress = message.fromAddress
val sender = coreContext.contactsManager.findContactByAddress(fromAddress)
val name = sender?.name ?: LinphoneUtils.getDisplayName(fromAddress)
val senderName = AppUtils.getFormattedString(
R.string.conversations_last_message_format,
name
)
lastMessageText.postValue("$senderName $text")
} else {
lastMessageText.postValue(text)
}
isLastMessageOutgoing.postValue(isOutgoing)
if (isOutgoing) {
lastMessageIcon.postValue(LinphoneUtils.getChatIconResId(message.state))
@ -258,8 +270,7 @@ class ConversationModel @WorkerThread constructor(val chatRoom: ChatRoom) {
TimestampUtils.timeToString(chatRoom.lastUpdateTime)
}
TimestampUtils.isYesterday(timestamp) -> {
val time = TimestampUtils.timeToString(chatRoom.lastUpdateTime)
AppUtils.getFormattedString(R.string.conversation_yesterday_timestamp, time)
AppUtils.getString(R.string.yesterday)
}
else -> {
TimestampUtils.toString(chatRoom.lastUpdateTime, onlyDate = true)

View file

@ -31,7 +31,8 @@ class EventLogModel @WorkerThread constructor(
isFromGroup: Boolean,
isGroupedWithPreviousOne: Boolean,
isGroupedWithNextOne: Boolean,
onContentClicked: ((file: String) -> Unit)? = null
onContentClicked: ((file: String) -> Unit)? = null,
onJoinConferenceClicked: ((uri: String) -> Unit)? = null
) {
companion object {
private const val TAG = "[Event Log Model]"
@ -68,7 +69,8 @@ class EventLogModel @WorkerThread constructor(
chatMessage.replyMessageId,
isGroupedWithPreviousOne,
isGroupedWithNextOne,
onContentClicked
onContentClicked,
onJoinConferenceClicked
)
}

View file

@ -90,6 +90,10 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
MutableLiveData<Event<String>>()
}
val conferenceToJoinEvent: MutableLiveData<Event<String>> by lazy {
MutableLiveData<Event<String>>()
}
val chatRoomFoundEvent = MutableLiveData<Event<Boolean>>()
lateinit var chatRoom: ChatRoom
@ -120,10 +124,14 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
avatarModel,
LinphoneUtils.isChatRoomAGroup(chatRoom),
group,
true
) { file ->
fileToDisplayEvent.postValue(Event(file))
}
true,
{ file ->
fileToDisplayEvent.postValue(Event(file))
},
{ conferenceUri ->
conferenceToJoinEvent.postValue(Event(conferenceUri))
}
)
)
events.postValue(list)
@ -411,10 +419,14 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
avatar,
groupChatRoom,
index > 0,
index == groupedEventLogs.size - 1
) { file ->
fileToDisplayEvent.postValue(Event(file))
}
index == groupedEventLogs.size - 1,
{ file ->
fileToDisplayEvent.postValue(Event(file))
},
{ conferenceUri ->
conferenceToJoinEvent.postValue(Event(conferenceUri))
}
)
eventsList.add(model)
index += 1

View file

@ -54,7 +54,10 @@ class MeetingsFragment : GenericFragment() {
}
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
if (findNavController().currentDestination?.id == R.id.scheduleMeetingFragment) {
if (
findNavController().currentDestination?.id == R.id.scheduleMeetingFragment ||
findNavController().currentDestination?.id == R.id.meetingWaitingRoomFragment
) {
// Holds fragment in place while new contact fragment slides over it
return AnimationUtils.loadAnimation(activity, R.anim.hold)
}

View file

@ -140,7 +140,7 @@
<ViewStub
android:id="@+id/meeting_info"
android:layout_width="wrap_content"
android:layout_width="@dimen/chat_bubble_meeting_invite_width"
android:layout_height="wrap_content"
android:visibility="@{model.meetingFound ? View.VISIBLE : View.GONE, default=gone}"
android:layout="@layout/chat_bubble_meeting_invite_content"

View file

@ -10,9 +10,8 @@
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_width="@dimen/chat_bubble_meeting_invite_width"
android:layout_height="wrap_content"
android:minWidth="300dp"
android:background="@drawable/shape_squircle_white_r10_background">
<View
@ -156,7 +155,7 @@
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style_300"
android:id="@+id/participants"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
@ -169,6 +168,7 @@
android:drawableStart="@drawable/users"
android:drawablePadding="4dp"
app:drawableTint="@color/gray_main2_600"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/join"
app:layout_constraintTop_toBottomOf="@id/description"/>

View file

@ -101,7 +101,7 @@
<ViewStub
android:id="@+id/meeting_info"
android:layout_width="wrap_content"
android:layout_width="@dimen/chat_bubble_meeting_invite_width"
android:layout_height="wrap_content"
android:visibility="@{model.meetingFound ? View.VISIBLE : View.GONE, default=gone}"
android:layout="@layout/chat_bubble_meeting_invite_content"

View file

@ -62,12 +62,19 @@
app:layout_constraintStart_toStartOf="@id/avatar"
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/unread_count_right_border"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="start"
app:constraint_referenced_ids="ephemeral, muted, date_time, last_sent_message_status" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/right_border"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="start"
app:constraint_referenced_ids="notifications_count, date_time" />
app:constraint_referenced_ids="notifications_count, date_time, ephemeral, muted, last_sent_message_status" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
@ -124,19 +131,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/name"
app:layout_constraintEnd_toStartOf="@id/date_time"/>
<ImageView
android:id="@+id/last_sent_message_status"
android:layout_width="@dimen/small_icon_size"
android:layout_height="@dimen/small_icon_size"
android:layout_marginEnd="10dp"
android:src="@{model.lastMessageIcon, default=@drawable/check}"
android:visibility="@{model.isLastMessageOutgoing ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/name"
app:layout_constraintBottom_toBottomOf="@id/name"
app:tint="@color/orange_main_500" />
app:layout_constraintEnd_toStartOf="@id/unread_count_right_border"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style_300"
@ -147,9 +142,21 @@
android:text="@{model.dateTime, default=`16:45`}"
android:textSize="12sp"
android:textColor="@color/gray_main2_500"
app:layout_constraintEnd_toStartOf="@id/last_sent_message_status"
app:layout_constraintTop_toTopOf="@id/last_sent_message_status"
app:layout_constraintBottom_toBottomOf="@id/last_sent_message_status" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/name"
app:layout_constraintBottom_toBottomOf="@id/name" />
<ImageView
android:id="@+id/last_sent_message_status"
android:layout_width="@dimen/small_icon_size"
android:layout_height="@dimen/small_icon_size"
android:layout_marginEnd="10dp"
android:src="@{model.lastMessageIcon, default=@drawable/check}"
android:visibility="@{model.isLastMessageOutgoing ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/date_time"
app:layout_constraintBottom_toTopOf="@id/separator"
app:tint="@color/orange_main_500" />
<ImageView
android:id="@+id/muted"
@ -158,7 +165,7 @@
android:layout_marginEnd="10dp"
android:src="@drawable/bell_simple_slash"
android:visibility="@{model.isMuted ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@id/last_sent_message_status"
app:layout_constraintTop_toBottomOf="@id/date_time"
app:layout_constraintBottom_toTopOf="@id/separator"
app:tint="@color/gray_main2_400" />

View file

@ -220,6 +220,12 @@
app:enterAnim="@anim/slide_in"
app:popExitAnim="@anim/slide_out"
app:launchSingleTop="true" />
<action
android:id="@+id/action_conversationsFragment_to_meetingWaitingRoomFragment"
app:destination="@id/meetingWaitingRoomFragment"
app:enterAnim="@anim/slide_in"
app:popExitAnim="@anim/slide_out"
app:launchSingleTop="true" />
</fragment>
<fragment
@ -260,10 +266,8 @@
<action
android:id="@+id/action_meetingsFragment_to_meetingWaitingRoomFragment"
app:destination="@id/meetingWaitingRoomFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:enterAnim="@anim/slide_in"
app:popExitAnim="@anim/slide_out"
app:launchSingleTop="true" />
</fragment>

View file

@ -68,6 +68,7 @@
<dimen name="chat_bubble_long_press_emoji_reaction_size">30sp</dimen>
<dimen name="chat_bubble_grid_image_size">88dp</dimen>
<dimen name="chat_bubble_big_image_max_size">150dp</dimen>
<dimen name="chat_bubble_meeting_invite_width">271dp</dimen>
<dimen name="chat_bubble_max_width">291dp</dimen>
<dimen name="chat_bubble_images_rounded_corner_radius">5dp</dimen>
<dimen name="chat_bubble_start_margin_when_avatar_displayed">10dp</dimen>

View file

@ -340,13 +340,13 @@
<string name="call_incoming_for_account">Incoming call for %s</string>
<string name="conversations_list_empty">No conversation for the moment…</string>
<string name="conversations_last_message_format">%s:</string>
<string name="conversation_action_mark_as_read">Mark as read</string>
<string name="conversation_action_mute">Mute</string>
<string name="conversation_action_unmute">Un-mute</string>
<string name="conversation_action_call">Call</string>
<string name="conversation_action_delete">Delete conversation</string>
<string name="conversation_action_leave_group">Leave the group</string>
<string name="conversation_yesterday_timestamp">Yesterday at %s</string>
<string name="new_conversation_title">New conversation</string>
<string name="new_conversation_search_bar_filter_hint">Search contact</string>
<string name="new_conversation_create_group">Create a group conversation</string>