Skip to content

Feature/aris/threads post release improvements #5959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
1 change: 1 addition & 0 deletions changelog.d/5959.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Multiple threads improvement (mainly UI)
5 changes: 5 additions & 0 deletions library/ui-styles/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,9 @@
<color name="shield_color_black">#17191C</color>
<color name="shield_color_warning">#FF4B55</color>

<!-- Badge Colors -->
<attr name="vctr_badge_color_border" format="color" />
<color name="vctr_badge_color_border_light">@color/palette_white</color>
<color name="vctr_badge_color_border_dark">@color/palette_black_950</color>

</resources>
2 changes: 1 addition & 1 deletion library/ui-styles/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<dimen name="menu_item_icon_size">24dp</dimen>
<dimen name="menu_item_size">48dp</dimen>
<dimen name="menu_item_ripple_size">48dp</dimen>
<dimen name="menu_item_width_small">38dp</dimen>
<dimen name="menu_item_width_small">34dp</dimen>

<!-- Composer -->
<dimen name="composer_min_height">56dp</dimen>
Expand Down
1 change: 1 addition & 0 deletions library/ui-styles/src/main/res/values/theme_dark.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<item name="vctr_toolbar_background">@color/element_system_dark</item>
<item name="vctr_message_bubble_inbound">@color/vctr_message_bubble_inbound_dark</item>
<item name="vctr_message_bubble_outbound">@color/vctr_message_bubble_outbound_dark</item>
<item name="vctr_badge_color_border">@color/vctr_badge_color_border_dark</item>

<!-- room message colors -->
<item name="vctr_notice_secondary">#61708B</item>
Expand Down
1 change: 1 addition & 0 deletions library/ui-styles/src/main/res/values/theme_light.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<item name="vctr_toolbar_background">@color/element_background_light</item>
<item name="vctr_message_bubble_inbound">@color/vctr_message_bubble_inbound_light</item>
<item name="vctr_message_bubble_outbound">@color/vctr_message_bubble_outbound_light</item>
<item name="vctr_badge_color_border">@color/vctr_badge_color_border_light</item>

<!-- room message colors -->
<item name="vctr_notice_secondary">#61708B</item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1529,7 +1529,7 @@ class TimelineFragment @Inject constructor(

views.composerLayout.views.composerEmojiButton.isVisible = vectorPreferences.showEmojiKeyboard()

if (isThreadTimeLine() && timelineArgs.threadTimelineArgs?.startsThread == true) {
if (isThreadTimeLine() && timelineArgs.threadTimelineArgs?.showKeyboard == true) {
// Show keyboard when the user started a thread
views.composerLayout.views.composerEditText.showKeyboard(andRequestFocus = true)
}
Expand Down Expand Up @@ -2443,7 +2443,11 @@ class TimelineFragment @Inject constructor(

private fun onReplyInThreadClicked(action: EventSharedAction.ReplyInThread) {
if (vectorPreferences.areThreadMessagesEnabled()) {
navigateToThreadTimeline(action.eventId, action.startsThread)
navigateToThreadTimeline(
rootThreadEventId = action.eventId,
startsThread = action.startsThread,
showKeyboard = true
)
} else {
displayThreadsBetaOptInDialog()
}
Expand All @@ -2453,7 +2457,7 @@ class TimelineFragment @Inject constructor(
* Navigate to Threads timeline for the specified rootThreadEventId
* using the ThreadsActivity.
*/
private fun navigateToThreadTimeline(rootThreadEventId: String, startsThread: Boolean = false) {
private fun navigateToThreadTimeline(rootThreadEventId: String, startsThread: Boolean = false, showKeyboard: Boolean = false) {
analyticsTracker.capture(Interaction.Name.MobileRoomThreadSummaryItem.toAnalyticsInteraction())
context?.let {
val roomThreadDetailArgs = ThreadTimelineArgs(
Expand All @@ -2462,7 +2466,8 @@ class TimelineFragment @Inject constructor(
displayName = timelineViewModel.getRoomSummary()?.displayName,
avatarUrl = timelineViewModel.getRoomSummary()?.avatarUrl,
roomEncryptionTrustLevel = timelineViewModel.getRoomSummary()?.roomEncryptionTrustLevel,
rootThreadEventId = rootThreadEventId
rootThreadEventId = rootThreadEventId,
showKeyboard = showKeyboard
)
navigator.openThread(it, roomThreadDetailArgs)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,25 @@ class SearchFragment @Inject constructor(
override fun onItemClicked(event: Event) =
navigateToEvent(event)

override fun onThreadSummaryClicked(event: Event) {
navigateToEvent(event, true)
}

/**
* Navigate and highlight the event. If this is a thread event,
* user will be redirected to the appropriate thread room
* @param event the event to navigate and highlight
* @param forceNavigateToThread force navigate within the thread (ex. when user clicks on thread summary)
*/
private fun navigateToEvent(event: Event) {
private fun navigateToEvent(event: Event, forceNavigateToThread: Boolean = false) {
val roomId = event.roomId ?: return
event.getRootThreadEventId()?.let {
val rootThreadEventId = if (forceNavigateToThread) {
event.eventId
} else {
event.getRootThreadEventId()
}

rootThreadEventId?.let {
val threadTimelineArgs = ThreadTimelineArgs(
roomId = roomId,
displayName = fragmentArgs.roomDisplayName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class SearchResultController @Inject constructor(

interface Listener {
fun onItemClicked(event: Event)
fun onThreadSummaryClicked(event: Event)
fun loadMore()
}

Expand Down Expand Up @@ -134,6 +135,7 @@ class SearchResultController @Inject constructor(
.threadSummaryFormatted(displayableEventFormatter.formatThreadSummary(event.threadDetails?.threadSummaryLatestEvent).toString())
.areThreadMessagesEnabled(userPreferencesProvider.areThreadMessagesEnabled())
.listener { listener?.onItemClicked(eventAndSender.event) }
.threadSummaryListener { listener?.onThreadSummaryClicked(eventAndSender.event) }
.let { result.add(it) }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ abstract class SearchResultItem : VectorEpoxyModel<SearchResultItem.Holder>() {
@EpoxyAttribute var areThreadMessagesEnabled: Boolean = false

@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var listener: ClickListener? = null
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var threadSummaryListener: ClickListener? = null

override fun bind(holder: Holder) {
super.bind(holder)
Expand All @@ -66,23 +67,24 @@ abstract class SearchResultItem : VectorEpoxyModel<SearchResultItem.Holder>() {
val displayName = it.threadSummarySenderInfo?.displayName
val avatarUrl = it.threadSummarySenderInfo?.avatarUrl
avatarRenderer.render(MatrixItem.UserItem(userId, displayName, avatarUrl), holder.threadSummaryAvatarImageView)
holder.threadSummaryContainer.onClick(threadSummaryListener)
} else {
showFromThread(holder)
}
} ?: run {
holder.threadSummaryConstraintLayout.isVisible = false
holder.threadSummaryContainer.isVisible = false
holder.fromThreadConstraintLayout.isVisible = false
}
}
}

private fun showThreadSummary(holder: Holder, show: Boolean = true) {
holder.threadSummaryConstraintLayout.isVisible = show
holder.threadSummaryContainer.isVisible = show
holder.fromThreadConstraintLayout.isVisible = !show
}

private fun showFromThread(holder: Holder, show: Boolean = true) {
holder.threadSummaryConstraintLayout.isVisible = !show
holder.threadSummaryContainer.isVisible = !show
holder.fromThreadConstraintLayout.isVisible = show
}

Expand All @@ -91,7 +93,7 @@ abstract class SearchResultItem : VectorEpoxyModel<SearchResultItem.Holder>() {
val memberNameView by bind<TextView>(R.id.messageMemberNameView)
val timeView by bind<TextView>(R.id.messageTimeView)
val contentView by bind<TextView>(R.id.messageContentView)
val threadSummaryConstraintLayout by bind<ConstraintLayout>(R.id.searchThreadSummaryConstraintLayout)
val threadSummaryContainer by bind<ConstraintLayout>(R.id.searchThreadSummaryContainer)
val threadSummaryCounterTextView by bind<TextView>(R.id.messageThreadSummaryCounterTextView)
val threadSummaryAvatarImageView by bind<ImageView>(R.id.messageThreadSummaryAvatarImageView)
val threadSummaryInfoTextView by bind<TextView>(R.id.messageThreadSummaryInfoTextView)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ data class ThreadTimelineArgs(
val avatarUrl: String?,
val roomEncryptionTrustLevel: RoomEncryptionTrustLevel?,
val rootThreadEventId: String? = null,
val startsThread: Boolean = false
val startsThread: Boolean = false,
val showKeyboard: Boolean = false
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package im.vector.app.features.home.room.threads.list.views
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
Expand Down Expand Up @@ -70,6 +71,16 @@ class ThreadListFragment @Inject constructor(
analyticsScreenName = MobileScreen.ScreenName.ThreadList
}

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)

menu.findItem(R.id.menu_thread_list_filter)?.let { menuItem ->
menuItem.actionView.setOnClickListener {
onOptionsItemSelected(menuItem)
}
}
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_thread_list_filter -> {
Expand All @@ -82,6 +93,9 @@ class ThreadListFragment @Inject constructor(

override fun onPrepareOptionsMenu(menu: Menu) {
withState(threadListViewModel) { state ->
val filterIcon = menu.findItem(R.id.menu_thread_list_filter).actionView
val filterBadge = filterIcon.findViewById<View>(R.id.threadListFilterBadge)
filterBadge.isVisible = state.shouldFilterThreads
when (threadListViewModel.canHomeserverUseThreading()) {
true -> menu.findItem(R.id.menu_thread_list_filter).isVisible = !state.threadSummaryList.invoke().isNullOrEmpty()
false -> menu.findItem(R.id.menu_thread_list_filter).isVisible = !state.rootThreadEventList.invoke().isNullOrEmpty()
Expand Down Expand Up @@ -146,9 +160,9 @@ class ThreadListFragment @Inject constructor(

override fun onThreadSummaryClicked(threadSummary: ThreadSummary) {
val roomThreadDetailArgs = ThreadTimelineArgs(
roomId = threadSummary.roomId,
displayName = threadSummary.rootThreadSenderInfo.displayName,
avatarUrl = threadSummary.rootThreadSenderInfo.avatarUrl,
roomId = threadListArgs.roomId,
displayName = threadListArgs.displayName,
avatarUrl = threadListArgs.avatarUrl,
roomEncryptionTrustLevel = null,
rootThreadEventId = threadSummary.rootEventId
)
Expand All @@ -157,9 +171,9 @@ class ThreadListFragment @Inject constructor(

override fun onThreadListClicked(timelineEvent: TimelineEvent) {
val threadTimelineArgs = ThreadTimelineArgs(
roomId = timelineEvent.roomId,
displayName = timelineEvent.senderInfo.displayName,
avatarUrl = timelineEvent.senderInfo.avatarUrl,
roomId = threadListArgs.roomId,
displayName = threadListArgs.displayName,
avatarUrl = threadListArgs.avatarUrl,
roomEncryptionTrustLevel = null,
rootThreadEventId = timelineEvent.eventId
)
Expand Down
29 changes: 29 additions & 0 deletions vector/src/main/res/drawable/thread_filter_badge.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item>
<shape
android:shape="oval">
<size
android:width="10dp"
android:height="10dp" />
<padding
android:bottom="3dp"
android:left="3dp"
android:right="3dp"
android:top="3dp" />
<stroke
android:color="?vctr_badge_color_border"
android:width="3dp"/>
</shape>
</item>

<item>
<shape android:shape="oval">
<size
android:width="10dp"
android:height="10dp" />
<solid android:color="?colorPrimary" />
</shape>
</item>
</layer-list>
2 changes: 1 addition & 1 deletion vector/src/main/res/layout/item_search_result.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
tools:text="@sample/messages.json/data/message" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/searchThreadSummaryConstraintLayout"
android:id="@+id/searchThreadSummaryContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constrainedWidth="true"
Expand Down
4 changes: 2 additions & 2 deletions vector/src/main/res/layout/item_thread.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
android:maxWidth="496dp"
android:minWidth="144dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingBottom="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/threadSummaryTitleTextView"
app:layout_constraintTop_toBottomOf="@id/threadSummaryRootMessageTextView"
Expand All @@ -108,4 +108,4 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/threadSummaryConstraintLayout"
app:layout_constraintTop_toBottomOf="@id/threadSummaryConstraintLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
38 changes: 38 additions & 0 deletions vector/src/main/res/layout/view_thread_list_filter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/menu_item_size"
android:layout_height="@dimen/menu_item_size">

<FrameLayout
android:layout_width="@dimen/menu_item_ripple_size"
android:layout_height="@dimen/menu_item_ripple_size"
android:layout_gravity="center"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<ImageView
android:layout_width="@dimen/menu_item_icon_size"
android:layout_height="@dimen/menu_item_icon_size"
android:layout_gravity="center"
android:src="@drawable/ic_filter"
tools:ignore="ContentDescription" />

<View
android:id="@+id/threadListFilterBadge"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="3dp"
android:layout_gravity="top|end"
android:background="@drawable/thread_filter_badge"
android:visibility="visible"
tools:visibility="visible" />

</FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
1 change: 0 additions & 1 deletion vector/src/main/res/layout/view_thread_room_summary.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:minEms="1"
android:textColor="?vctr_content_secondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/messageThreadSummaryImageView"
Expand Down
7 changes: 4 additions & 3 deletions vector/src/main/res/menu/menu_thread_list.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

<item
android:id="@+id/menu_thread_list_filter"
android:icon="@drawable/ic_filter"
android:title="@string/room_threads_filter"
app:actionLayout="@layout/view_thread_list_filter"
app:iconTint="?vctr_content_secondary"
app:showAsAction="ifRoom" />
app:showAsAction="always"
tools:visible="true" />

</menu>
</menu>