Home: start reworking room list.

This commit is contained in:
ganfra 2019-05-17 10:19:19 +02:00 committed by Benoit Marty
parent 275521db70
commit c0fd06fd2d
9 changed files with 106 additions and 47 deletions

View File

@ -23,6 +23,7 @@ import im.vector.riotredesign.core.error.ErrorFormatter
import im.vector.riotredesign.core.resources.LocaleProvider
import im.vector.riotredesign.core.resources.StringArrayProvider
import im.vector.riotredesign.core.resources.StringProvider
import im.vector.riotredesign.features.home.HomeRoomListObservableStore
import im.vector.riotredesign.features.home.group.SelectedGroupStore
import im.vector.riotredesign.features.home.room.list.RoomSummaryComparator
import im.vector.riotredesign.features.notifications.NotificationDrawerManager
@ -52,6 +53,10 @@ class AppModule(private val context: Context) {
SelectedGroupStore()
}
single {
HomeRoomListObservableStore()
}
single {
RoomSummaryComparator()
}

View File

@ -29,4 +29,9 @@ object DateProvider {
return LocalDateTime.ofInstant(instant, zoneId)
}
fun currentLocalDateTime(): LocalDateTime {
val instant = Instant.now()
return LocalDateTime.ofInstant(instant, zoneId)
}
}

View File

@ -25,14 +25,7 @@ import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserControl
import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserPresenter
import im.vector.riotredesign.features.home.group.GroupSummaryController
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
import im.vector.riotredesign.features.home.room.detail.timeline.factory.CallItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.factory.DefaultItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.factory.MessageItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.factory.RoomHistoryVisibilityItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.factory.RoomMemberItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.factory.RoomNameItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.factory.RoomTopicItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.factory.TimelineItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.factory.*
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
import im.vector.riotredesign.features.home.room.list.RoomSummaryController
@ -56,36 +49,36 @@ class HomeModule {
HomeNavigator()
}
scope(HOME_SCOPE) {
HomeRoomListObservableStore()
}
scope(HOME_SCOPE) {
HomePermalinkHandler(get())
}
// Fragment scopes
factory {
TimelineDateFormatter(get())
}
factory { (fragment: Fragment) ->
val eventHtmlRenderer = EventHtmlRenderer(GlideApp.with(fragment), fragment.requireContext(), get())
val timelineDateFormatter = TimelineDateFormatter(get())
val timelineMediaSizeProvider = TimelineMediaSizeProvider()
val colorProvider = ColorProvider(fragment.requireContext())
val timelineDateFormatter = get<TimelineDateFormatter>()
val messageItemFactory = MessageItemFactory(colorProvider, timelineMediaSizeProvider, timelineDateFormatter, eventHtmlRenderer)
val timelineItemFactory = TimelineItemFactory(messageItemFactory = messageItemFactory,
roomNameItemFactory = RoomNameItemFactory(get()),
roomTopicItemFactory = RoomTopicItemFactory(get()),
roomMemberItemFactory = RoomMemberItemFactory(get()),
roomHistoryVisibilityItemFactory = RoomHistoryVisibilityItemFactory(get()),
callItemFactory = CallItemFactory(get()),
defaultItemFactory = DefaultItemFactory()
roomNameItemFactory = RoomNameItemFactory(get()),
roomTopicItemFactory = RoomTopicItemFactory(get()),
roomMemberItemFactory = RoomMemberItemFactory(get()),
roomHistoryVisibilityItemFactory = RoomHistoryVisibilityItemFactory(get()),
callItemFactory = CallItemFactory(get()),
defaultItemFactory = DefaultItemFactory()
)
TimelineEventController(timelineDateFormatter, timelineItemFactory, timelineMediaSizeProvider)
}
factory {
RoomSummaryController(get())
RoomSummaryController(get(), get())
}
factory {

View File

@ -29,6 +29,7 @@ import im.vector.matrix.android.api.session.room.model.tag.RoomTag
import im.vector.riotredesign.core.platform.VectorViewModel
import im.vector.riotredesign.core.utils.LiveEvent
import im.vector.riotredesign.features.home.HomeRoomListObservableStore
import io.reactivex.Observable
import org.koin.android.ext.android.get
typealias RoomListFilterName = CharSequence
@ -50,7 +51,7 @@ class RoomListViewModel(initialState: RoomListViewState,
}
}
private val displayMode = initialState.displayMode
private val roomListFilter = BehaviorRelay.createDefault<Option<RoomListFilterName>>(Option.empty())
private val _openRoomLiveData = MutableLiveData<LiveEvent<String>>()
@ -86,15 +87,27 @@ class RoomListViewModel(initialState: RoomListViewState,
private fun observeRoomSummaries() {
homeRoomListObservableSource.observe()
homeRoomListObservableSource
.observe()
.flatMapSingle {
Observable.fromIterable(it)
.filter(filterByDisplayMode(displayMode))
.toList()
}
.map { buildRoomSummaries(it) }
.execute { async ->
copy(
asyncRooms = async
)
copy(asyncRooms = async)
}
}
private fun filterByDisplayMode(displayMode: RoomListFragment.DisplayMode) = { roomSummary: RoomSummary ->
when (displayMode) {
RoomListFragment.DisplayMode.HOME -> roomSummary.notificationCount > 0
RoomListFragment.DisplayMode.PEOPLE -> roomSummary.isDirect
RoomListFragment.DisplayMode.ROOMS -> !roomSummary.isDirect
}
}
private fun buildRoomSummaries(rooms: List<RoomSummary>): RoomSummaries {
val invites = ArrayList<RoomSummary>()
val favourites = ArrayList<RoomSummary>()

View File

@ -24,6 +24,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.riotredesign.R
data class RoomListViewState(
val displayMode: RoomListFragment.DisplayMode,
val asyncRooms: Async<RoomSummaries> = Uninitialized,
val isInviteExpanded: Boolean = true,
val isFavouriteRoomsExpanded: Boolean = true,
@ -33,6 +34,8 @@ data class RoomListViewState(
val isServerNoticeRoomsExpanded: Boolean = true
) : MvRxState {
constructor(args: RoomListParams) : this(displayMode = args.displayMode)
fun isCategoryExpanded(roomCategory: RoomCategory): Boolean {
return when (roomCategory) {
RoomCategory.INVITE -> isInviteExpanded

View File

@ -19,9 +19,13 @@ package im.vector.riotredesign.features.home.room.list
import androidx.annotation.StringRes
import com.airbnb.epoxy.TypedEpoxyController
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.core.resources.DateProvider
import im.vector.riotredesign.core.resources.StringProvider
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
class RoomSummaryController(private val stringProvider: StringProvider
class RoomSummaryController(private val stringProvider: StringProvider,
private val timelineDateFormatter: TimelineDateFormatter
) : TypedEpoxyController<RoomListViewState>() {
var callback: Callback? = null
@ -76,9 +80,29 @@ class RoomSummaryController(private val stringProvider: StringProvider
val unreadCount = roomSummary.notificationCount
val showHighlighted = roomSummary.highlightCount > 0
var lastMessageFormatted: CharSequence = ""
var lastMessageTime: CharSequence = ""
val lastMessage = roomSummary.lastMessage
if (lastMessage != null) {
val date = lastMessage.localDateTime()
val currentData = DateProvider.currentLocalDateTime()
val isSameDay = date.toLocalDate() == currentData.toLocalDate()
//TODO: get formatted
lastMessageFormatted = lastMessage.content?.toString() ?: ""
lastMessageTime = if (isSameDay) {
timelineDateFormatter.formatMessageHour(date)
} else {
//TODO: change this
timelineDateFormatter.formatMessageDay(date)
}
}
roomSummaryItem {
id(roomSummary.roomId)
roomId(roomSummary.roomId)
lastEventTime(lastMessageTime)
lastFormattedEvent(lastMessageFormatted)
roomName(roomSummary.displayName)
avatarUrl(roomSummary.avatarUrl)
showHighlighted(showHighlighted)

View File

@ -32,6 +32,8 @@ abstract class RoomSummaryItem : VectorEpoxyModel<RoomSummaryItem.Holder>() {
@EpoxyAttribute lateinit var roomName: CharSequence
@EpoxyAttribute lateinit var roomId: String
@EpoxyAttribute lateinit var lastFormattedEvent: CharSequence
@EpoxyAttribute lateinit var lastEventTime: CharSequence
@EpoxyAttribute var avatarUrl: String? = null
@EpoxyAttribute var unreadCount: Int = 0
@EpoxyAttribute var showHighlighted: Boolean = false
@ -40,15 +42,17 @@ abstract class RoomSummaryItem : VectorEpoxyModel<RoomSummaryItem.Holder>() {
override fun bind(holder: Holder) {
super.bind(holder)
holder.unreadCounterBadgeView.render(unreadCount, showHighlighted)
holder.rootView.setOnClickListener { listener?.invoke() }
holder.titleView.text = roomName
holder.lastEventTimeView.text = lastEventTime
holder.lastEventView.text = lastFormattedEvent
AvatarRenderer.render(avatarUrl, roomId, roomName.toString(), holder.avatarImageView)
}
class Holder : VectorEpoxyHolder() {
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomUnreadCounterBadgeView)
val titleView by bind<TextView>(R.id.roomNameView)
val lastEventView by bind<TextView>(R.id.roomLastEventView)
val lastEventTimeView by bind<TextView>(R.id.roomLastEventTimeView)
val avatarImageView by bind<ImageView>(R.id.roomAvatarImageView)
val rootView by bind<ViewGroup>(R.id.itemRoomLayout)
}

View File

@ -9,7 +9,8 @@
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="48dp"
android:paddingBottom="16dp"
android:paddingTop="16dp"
android:paddingStart="8dp"
android:paddingLeft="8dp"
android:paddingEnd="16dp"
@ -17,8 +18,8 @@
<ImageView
android:id="@+id/roomAvatarImageView"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
app:layout_constraintBottom_toBottomOf="parent"
@ -33,30 +34,38 @@
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:duplicateParentState="true"
android:textColor="@color/color_room_title"
android:textColor="@color/black_87"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/roomUnreadCounterBadgeView"
app:layout_constraintEnd_toStartOf="@+id/roomLastEventTimeView"
app:layout_constraintStart_toEndOf="@id/roomAvatarImageView"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
<im.vector.riotredesign.features.home.room.list.UnreadCounterBadgeView
android:id="@+id/roomUnreadCounterBadgeView"
<TextView
android:id="@+id/roomLastEventView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@color/black_38"
android:textSize="14sp"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/roomNameView"
app:layout_constraintTop_toBottomOf="@+id/roomNameView"
tools:text="@tools:sample/lorem/random" />
<TextView
android:id="@+id/roomLastEventTimeView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minWidth="24dp"
android:minHeight="24dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:textColor="@android:color/white"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:textColor="@color/black_38"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintBaseline_toBaselineOf="@id/messageMemberNameView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:background="@drawable/bg_unread_highlight"
tools:text="115" />
app:layout_constraintStart_toEndOf="@id/messageMemberNameView"
tools:text="@tools:sample/date/hhmm" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -16,6 +16,9 @@
<color name="pale_grey_two">#ebedf8</color>
<color name="brown_grey">#a5a5a5</color>
<color name="grey_lynch">#61708B</color>
<color name="black_87">#de000000</color>
<color name="black_38">#61000000</color>
<color name="black_37">#5d000000</color>
<color name="black">#000000</color>
<color name="black_87">#de000000</color>