Clean a bit code of timeline + show not handled events message

This commit is contained in:
ganfra 2018-11-02 17:37:37 +01:00
parent 6d9ec2789b
commit 2885b510ab
15 changed files with 132 additions and 71 deletions

View File

@ -1,5 +1,7 @@
package im.vector.riotredesign.features.home package im.vector.riotredesign.features.home


import im.vector.riotredesign.features.home.room.detail.timeline.MessageItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.TextItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineDateFormatter import im.vector.riotredesign.features.home.room.detail.timeline.TimelineDateFormatter
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
import org.koin.dsl.context.ModuleDefinition import org.koin.dsl.context.ModuleDefinition
@ -14,12 +16,20 @@ class HomeModule(private val homeActivity: HomeActivity) : Module {
homeActivity as HomeNavigator homeActivity as HomeNavigator
} }


factory { single {
TimelineDateFormatter(get()) TimelineDateFormatter(get())
} }


factory { single {
TimelineEventController(get()) MessageItemFactory(get())
}

single {
TextItemFactory()
}

single {
TimelineEventController(get(), get(), get())
} }


}.invoke() }.invoke()

View File

@ -1,8 +1,13 @@
package im.vector.riotredesign.features.home.room.detail.timeline package im.vector.riotredesign.features.home.room.detail.timeline


import android.content.Context import im.vector.riotredesign.R
import android.widget.FrameLayout import im.vector.riotredesign.core.epoxy.KotlinModel
import com.airbnb.epoxy.ModelView


@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT) class BlankItem
class BlankItem(context: Context) : FrameLayout(context) : KotlinModel(R.layout.item_event_blank) {

override fun bind() {
//no-op
}

}

View File

@ -4,7 +4,7 @@ import android.widget.TextView
import im.vector.riotredesign.R import im.vector.riotredesign.R
import im.vector.riotredesign.core.epoxy.KotlinModel import im.vector.riotredesign.core.epoxy.KotlinModel


data class TimelineDaySeparatorItem( data class DaySeparatorItem(
val formattedDay: CharSequence val formattedDay: CharSequence
) : KotlinModel(R.layout.item_event_day_separator) { ) : KotlinModel(R.layout.item_event_day_separator) {


View File

@ -7,7 +7,7 @@ import im.vector.riotredesign.R
import im.vector.riotredesign.core.epoxy.KotlinModel import im.vector.riotredesign.core.epoxy.KotlinModel
import im.vector.riotredesign.features.home.AvatarRenderer import im.vector.riotredesign.features.home.AvatarRenderer


data class TimelineMessageItem( data class MessageItem(
val message: CharSequence? = null, val message: CharSequence? = null,
val time: CharSequence? = null, val time: CharSequence? = null,
val avatarUrl: String?, val avatarUrl: String?,

View File

@ -0,0 +1,34 @@
package im.vector.riotredesign.features.home.room.detail.timeline

import im.vector.matrix.android.api.session.events.model.EnrichedEvent
import im.vector.matrix.android.api.session.events.model.roomMember
import im.vector.matrix.android.api.session.room.model.MessageContent
import org.threeten.bp.LocalDateTime

class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatter) {

private val messagesDisplayedWithInformation = HashSet<String?>()

fun create(event: EnrichedEvent, nextEvent: EnrichedEvent?, addDaySeparator: Boolean, date: LocalDateTime): MessageItem? {
val messageContent = event.root.content<MessageContent>()
val roomMember = event.roomMember()
if (messageContent == null || roomMember == null) {
return null
}
val nextRoomMember = nextEvent?.roomMember()
if (addDaySeparator || nextRoomMember != roomMember) {
messagesDisplayedWithInformation.add(event.root.eventId)
}
val showInformation = messagesDisplayedWithInformation.contains(event.root.eventId)

return MessageItem(
message = messageContent.body,
avatarUrl = roomMember.avatarUrl,
showInformation = showInformation,
time = timelineDateFormatter.formatMessageHour(date),
memberName = roomMember.displayName
)
}


}

View File

@ -4,13 +4,13 @@ import android.widget.TextView
import im.vector.riotredesign.R import im.vector.riotredesign.R
import im.vector.riotredesign.core.epoxy.KotlinModel import im.vector.riotredesign.core.epoxy.KotlinModel


data class TimelineEventItem( data class TextItem(
val title: String val text: CharSequence? = null
) : KotlinModel(R.layout.item_event) { ) : KotlinModel(R.layout.item_event_text) {


val titleView by bind<TextView>(R.id.titleView) private val messageView by bind<TextView>(R.id.stateMessageView)


override fun bind() { override fun bind() {
titleView.text = title messageView.text = text
} }
} }

View File

@ -0,0 +1,12 @@
package im.vector.riotredesign.features.home.room.detail.timeline

import im.vector.matrix.android.api.session.events.model.EnrichedEvent

class TextItemFactory {

fun create(event: EnrichedEvent): TextItem? {
val text = "${event.root.type} events are not yet handled"
return TextItem(text = text)
}

}

View File

@ -5,18 +5,17 @@ import com.airbnb.epoxy.EpoxyAsyncUtil
import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyController
import im.vector.matrix.android.api.session.events.model.EnrichedEvent import im.vector.matrix.android.api.session.events.model.EnrichedEvent
import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.roomMember
import im.vector.matrix.android.api.session.room.model.MessageContent
import im.vector.riotredesign.core.extensions.localDateTime import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.features.home.LoadingItemModel_ import im.vector.riotredesign.features.home.LoadingItemModel_


class TimelineEventController(private val timelineDateFormatter: TimelineDateFormatter) : EpoxyController( class TimelineEventController(private val messageItemFactory: MessageItemFactory,
private val textItemFactory: TextItemFactory,
private val dateFormatter: TimelineDateFormatter
) : EpoxyController(
EpoxyAsyncUtil.getAsyncBackgroundHandler(), EpoxyAsyncUtil.getAsyncBackgroundHandler(),
EpoxyAsyncUtil.getAsyncBackgroundHandler() EpoxyAsyncUtil.getAsyncBackgroundHandler()
) { ) {


private val messagesDisplayedWithInformation = HashSet<String?>()

private val pagedListCallback = object : PagedList.Callback() { private val pagedListCallback = object : PagedList.Callback() {
override fun onChanged(position: Int, count: Int) { override fun onChanged(position: Int, count: Int) {
requestModelBuild() requestModelBuild()
@ -54,38 +53,18 @@ class TimelineEventController(private val timelineDateFormatter: TimelineDateFor
val nextDate = nextEvent?.root?.localDateTime() val nextDate = nextEvent?.root?.localDateTime()
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate() val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()


if (event.root.type == EventType.MESSAGE) { val item = when (event.root.type) {
val messageContent = event.root.content<MessageContent>() EventType.MESSAGE -> messageItemFactory.create(event, nextEvent, addDaySeparator, date)
val roomMember = event.roomMember() else -> textItemFactory.create(event)
if (messageContent == null || roomMember == null) {
continue
} }
item
?.onBind { timeline?.loadAround(index) }
?.id(event.root.eventId)
?.addTo(this)


val nextRoomMember = nextEvent?.roomMember()
if (addDaySeparator || nextRoomMember != roomMember) {
messagesDisplayedWithInformation.add(event.root.eventId)
}
val showInformation = messagesDisplayedWithInformation.contains(event.root.eventId)

TimelineMessageItem(
message = messageContent.body,
avatarUrl = roomMember.avatarUrl,
showInformation = showInformation,
time = timelineDateFormatter.formatMessageHour(date),
memberName = roomMember.displayName
)
.onBind { timeline?.loadAround(index) }
.id(event.root.eventId)
.addTo(this)
} else {
BlankItemModel_()
.id(event.root.eventId)
.onBind { _, _, _ -> timeline?.loadAround(index) }
.addTo(this)
}
if (addDaySeparator) { if (addDaySeparator) {
val formattedDay = timelineDateFormatter.formatMessageDay(date) val formattedDay = dateFormatter.formatMessageDay(date)
TimelineDaySeparatorItem(formattedDay).id(formattedDay).addTo(this) DaySeparatorItem(formattedDay).id(formattedDay).addTo(this)
} }
} }



View File

@ -15,8 +15,8 @@ data class RoomSummaryItem(
val listener: (() -> Unit)? = null val listener: (() -> Unit)? = null
) : KotlinModel(R.layout.item_room) { ) : KotlinModel(R.layout.item_room) {


private val titleView by bind<TextView>(R.id.titleView) private val titleView by bind<TextView>(R.id.roomNameView)
private val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView) private val avatarImageView by bind<ImageView>(R.id.roomAvatarImageView)
private val rootView by bind<CheckableFrameLayout>(R.id.itemRoomLayout) private val rootView by bind<CheckableFrameLayout>(R.id.itemRoomLayout)


override fun bind() { override fun bind() {

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/titleView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="80dp"
android:padding="16dp"
android:textSize="14sp" />

View File

@ -0,0 +1,3 @@
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp" />

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/stateMessageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="64dp"
android:gravity="center_vertical"
android:padding="16dp"
android:textColor="?attr/colorAccent"
android:textSize="14sp"
android:textStyle="italic"
tools:text="Mon item" />

View File

@ -21,7 +21,7 @@
android:minHeight="48dp"> android:minHeight="48dp">


<ImageView <ImageView
android:id="@+id/messageAvatarImageView" android:id="@+id/roomAvatarImageView"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
@ -31,7 +31,7 @@
tools:src="@tools:sample/avatars" /> tools:src="@tools:sample/avatars" />


<TextView <TextView
android:id="@+id/titleView" android:id="@+id/roomNameView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
@ -40,7 +40,7 @@
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/messageAvatarImageView" app:layout_constraintStart_toEndOf="@id/roomAvatarImageView"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names" />



View File

@ -43,11 +43,4 @@ data class Event(
return moshiAdapter.fromJsonValue(data) return moshiAdapter.fromJsonValue(data)
} }


val isCallEvent: Boolean by lazy {
EventType.CALL_INVITE == type
|| EventType.CALL_CANDIDATES == type
|| EventType.CALL_ANSWER == type
|| EventType.CALL_HANGUP == type
}

} }

View File

@ -46,4 +46,25 @@ object EventType {
const val CALL_ANSWER = "m.call.answer" const val CALL_ANSWER = "m.call.answer"
const val CALL_HANGUP = "m.call.hangup" const val CALL_HANGUP = "m.call.hangup"


private val STATE_EVENTS = listOf(
STATE_ROOM_NAME,
STATE_ROOM_TOPIC,
STATE_ROOM_AVATAR,
STATE_ROOM_MEMBER,
STATE_ROOM_THIRD_PARTY_INVITE,
STATE_ROOM_CREATE,
STATE_ROOM_JOIN_RULES,
STATE_ROOM_GUEST_ACCESS,
STATE_ROOM_POWER_LEVELS,
STATE_ROOM_TOMBSTONE,
STATE_HISTORY_VISIBILITY,
STATE_RELATED_GROUPS,
STATE_PINNED_EVENT
)


fun isStateEvent(type: String): Boolean {
return STATE_EVENTS.contains(type)
}

} }