Fix some timeline issues and rename EnrichedEvent to TimelineEvent as it's only used in this context.

This commit is contained in:
ganfra
2019-01-14 16:18:39 +01:00
parent 34e08705dd
commit b2cdeb87f4
31 changed files with 170 additions and 179 deletions

View File

@ -3,7 +3,7 @@ package im.vector.riotredesign.core.extensions
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.LiveData
import android.arch.lifecycle.Observer
import im.vector.riotredesign.core.utils.Event
import im.vector.riotredesign.core.utils.LiveEvent
import im.vector.riotredesign.core.utils.EventObserver
inline fun <T> LiveData<T>.observeK(owner: LifecycleOwner, crossinline observer: (T?) -> Unit) {
@ -14,6 +14,6 @@ inline fun <T> LiveData<T>.observeNotNull(owner: LifecycleOwner, crossinline obs
this.observe(owner, Observer { it?.run(observer) })
}
inline fun <T> LiveData<Event<T>>.observeEvent(owner: LifecycleOwner, crossinline observer: (T) -> Unit) {
inline fun <T> LiveData<LiveEvent<T>>.observeEvent(owner: LifecycleOwner, crossinline observer: (T) -> Unit) {
this.observe(owner, EventObserver { it.run(observer) })
}

View File

@ -1,6 +0,0 @@
package im.vector.riotredesign.core.utils
object Constants {
}

View File

@ -1,63 +0,0 @@
package im.vector.riotredesign.core.utils
import android.os.Binder
import android.os.Bundle
import android.support.v4.app.BundleCompat
import android.support.v4.app.Fragment
import kotlin.reflect.KProperty
class FragmentArgumentDelegate<T : Any> : kotlin.properties.ReadWriteProperty<Fragment, T?> {
var value: T? = null
override operator fun getValue(thisRef: android.support.v4.app.Fragment, property: kotlin.reflect.KProperty<*>): T? {
if (value == null) {
val args = thisRef.arguments
@Suppress("UNCHECKED_CAST")
value = args?.get(property.name) as T?
}
return value
}
override operator fun setValue(thisRef: Fragment, property: KProperty<*>, value: T?) {
if (value == null) return
if (thisRef.arguments == null) {
thisRef.arguments = Bundle()
}
val args = thisRef.arguments!!
val key = property.name
when (value) {
is String -> args.putString(key, value)
is Int -> args.putInt(key, value)
is Short -> args.putShort(key, value)
is Long -> args.putLong(key, value)
is Byte -> args.putByte(key, value)
is ByteArray -> args.putByteArray(key, value)
is Char -> args.putChar(key, value)
is CharArray -> args.putCharArray(key, value)
is CharSequence -> args.putCharSequence(key, value)
is Float -> args.putFloat(key, value)
is Bundle -> args.putBundle(key, value)
is Binder -> BundleCompat.putBinder(args, key, value)
is android.os.Parcelable -> args.putParcelable(key, value)
is java.io.Serializable -> args.putSerializable(key, value)
else -> throw IllegalStateException("Type ${value.javaClass.name} of property ${property.name} is not supported")
}
}
}
class UnsafeFragmentArgumentDelegate<T : Any> : kotlin.properties.ReadWriteProperty<Fragment, T> {
private val innerDelegate = FragmentArgumentDelegate<T>()
override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) {
innerDelegate.setValue(thisRef, property, value)
}
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
return innerDelegate.getValue(thisRef, property)!!
}
}

View File

@ -2,7 +2,7 @@ package im.vector.riotredesign.core.utils
import android.arch.lifecycle.Observer
open class Event<out T>(private val content: T) {
open class LiveEvent<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
@ -26,13 +26,13 @@ open class Event<out T>(private val content: T) {
}
/**
* An [Observer] for [Event]s, simplifying the pattern of checking if the [Event]'s content has
* An [Observer] for [LiveEvent]s, simplifying the pattern of checking if the [LiveEvent]'s content has
* already been handled.
*
* [onEventUnhandledContent] is *only* called if the [Event]'s contents has not been handled.
* [onEventUnhandledContent] is *only* called if the [LiveEvent]'s contents has not been handled.
*/
class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<Event<T>> {
override fun onChanged(event: Event<T>?) {
class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<LiveEvent<T>> {
override fun onChanged(event: LiveEvent<T>?) {
event?.getContentIfNotHandled()?.let { value ->
onEventUnhandledContent(value)
}

View File

@ -9,7 +9,7 @@ import im.vector.matrix.android.api.Matrix
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.rx.rx
import im.vector.riotredesign.core.platform.RiotViewModel
import im.vector.riotredesign.core.utils.Event
import im.vector.riotredesign.core.utils.LiveEvent
import im.vector.riotredesign.features.home.room.list.RoomSelectionRepository
import io.reactivex.rxkotlin.subscribeBy
import org.koin.android.ext.android.get
@ -31,8 +31,8 @@ class HomeActivityViewModel(state: EmptyState,
}
}
private val _openRoomLiveData = MutableLiveData<Event<String>>()
val openRoomLiveData: LiveData<Event<String>>
private val _openRoomLiveData = MutableLiveData<LiveEvent<String>>()
val openRoomLiveData: LiveData<LiveEvent<String>>
get() = _openRoomLiveData
init {
@ -40,7 +40,7 @@ class HomeActivityViewModel(state: EmptyState,
if (lastSelectedRoom == null) {
getTheFirstRoomWhenAvailable()
} else {
_openRoomLiveData.postValue(Event(lastSelectedRoom))
_openRoomLiveData.postValue(LiveEvent(lastSelectedRoom))
}
}
@ -51,7 +51,7 @@ class HomeActivityViewModel(state: EmptyState,
.subscribeBy {
val firstRoom = it.firstOrNull()
if (firstRoom != null) {
_openRoomLiveData.postValue(Event(firstRoom.roomId))
_openRoomLiveData.postValue(LiveEvent(firstRoom.roomId))
}
}
.disposeOnClear()

View File

@ -23,7 +23,6 @@ class HomeNavigator {
if (!addToBackstack && isRoomOpened(roomId)) {
return
}
currentRoomId = roomId
activity?.let {
val args = RoomDetailArgs(roomId, eventId)
val roomDetailFragment = RoomDetailFragment.newInstance(args)
@ -31,6 +30,7 @@ class HomeNavigator {
if (addToBackstack) {
it.addFragmentToBackstack(roomDetailFragment, R.id.homeDetailFragmentContainer, roomId)
} else {
currentRoomId = roomId
clearBackStack(it.supportFragmentManager)
it.replaceFragment(roomDetailFragment, R.id.homeDetailFragmentContainer)
}

View File

@ -73,7 +73,7 @@ class RoomDetailFragment : RiotFragment(), TimelineEventController.Callback {
scrollOnNewMessageCallback = ScrollOnNewMessageCallback(layoutManager)
recyclerView.layoutManager = layoutManager
recyclerView.setHasFixedSize(true)
//timelineEventController.addModelBuildListener { it.dispatchTo(scrollOnNewMessageCallback) }
timelineEventController.addModelBuildListener { it.dispatchTo(scrollOnNewMessageCallback) }
recyclerView.setController(timelineEventController)
timelineEventController.callback = this
}
@ -95,8 +95,15 @@ class RoomDetailFragment : RiotFragment(), TimelineEventController.Callback {
private fun renderTimeline(state: RoomDetailViewState) {
when (state.asyncTimelineData) {
is Success -> timelineEventController.update(state.asyncTimelineData())
is Success -> {
val timelineData = state.asyncTimelineData()
val lockAutoScroll = timelineData?.let {
it.events == timelineEventController.currentList && it.isLoadingForward
} ?: true
scrollOnNewMessageCallback.isLocked.set(lockAutoScroll)
timelineEventController.update(timelineData)
}
}
}

View File

@ -6,10 +6,10 @@ import java.util.concurrent.atomic.AtomicBoolean
class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager) : DefaultListUpdateCallback {
val hasBeenUpdated = AtomicBoolean(false)
var isLocked = AtomicBoolean(true)
override fun onInserted(position: Int, count: Int) {
if (hasBeenUpdated.compareAndSet(true, false) && position == 0 && layoutManager.findFirstVisibleItemPosition() == 0) {
if (isLocked.compareAndSet(false, true) && position == 0 && layoutManager.findFirstVisibleItemPosition() == 0) {
layoutManager.scrollToPosition(0)
}
}

View File

@ -4,7 +4,7 @@ import android.text.SpannableStringBuilder
import android.text.util.Linkify
import im.vector.matrix.android.api.permalinks.MatrixLinkify
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
import im.vector.matrix.android.api.session.events.model.TimelineEvent
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.MessageContent
import org.threeten.bp.LocalDateTime
@ -13,8 +13,8 @@ class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatte
private val messagesDisplayedWithInformation = HashSet<String?>()
fun create(event: EnrichedEvent,
nextEvent: EnrichedEvent?,
fun create(event: TimelineEvent,
nextEvent: TimelineEvent?,
addDaySeparator: Boolean,
date: LocalDateTime,
callback: TimelineEventController.Callback?

View File

@ -1,10 +1,10 @@
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.TimelineEvent
class TextItemFactory {
fun create(event: EnrichedEvent): TextItem? {
fun create(event: TimelineEvent): TextItem? {
val text = "${event.root.type} events are not yet handled"
return TextItem(text = text)
}

View File

@ -2,7 +2,7 @@ package im.vector.riotredesign.features.home.room.detail.timeline
import com.airbnb.epoxy.EpoxyAsyncUtil
import com.airbnb.epoxy.EpoxyModel
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
import im.vector.matrix.android.api.session.events.model.TimelineEvent
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.timeline.TimelineData
import im.vector.riotredesign.core.extensions.localDateTime
@ -13,7 +13,7 @@ class TimelineEventController(private val roomId: String,
private val messageItemFactory: MessageItemFactory,
private val textItemFactory: TextItemFactory,
private val dateFormatter: TimelineDateFormatter
) : PagedListEpoxyController<EnrichedEvent>(
) : PagedListEpoxyController<TimelineEvent>(
EpoxyAsyncUtil.getAsyncBackgroundHandler(),
EpoxyAsyncUtil.getAsyncBackgroundHandler()
) {
@ -38,7 +38,7 @@ class TimelineEventController(private val roomId: String,
}
override fun buildItemModels(currentPosition: Int, items: List<EnrichedEvent?>): List<EpoxyModel<*>> {
override fun buildItemModels(currentPosition: Int, items: List<TimelineEvent?>): List<EpoxyModel<*>> {
if (items.isNullOrEmpty()) {
return emptyList()
}

View File

@ -70,6 +70,9 @@ abstract class PagedListEpoxyController<T>(
modelBuildingHandler = modelBuildingHandler
)
var currentList: PagedList<T>? = null
private set
final override fun buildModels() {
addModels(modelCache.getModels())
}
@ -107,6 +110,7 @@ abstract class PagedListEpoxyController<T>(
* to [buildItemModel] with items from the previous list.
*/
fun submitList(newList: PagedList<T>?) {
currentList = newList
modelCache.submitList(newList)
}