Still WIP for Paging integration

This commit is contained in:
ganfra 2018-10-21 20:27:50 +02:00
parent 702abccb38
commit d71ae02162
11 changed files with 127 additions and 31 deletions

View file

@ -0,0 +1,14 @@
package im.vector.riotredesign.features.home
import android.support.v7.util.DiffUtil
import im.vector.matrix.android.api.session.events.model.Event
class EventDiffUtilCallback : DiffUtil.ItemCallback<Event>() {
override fun areItemsTheSame(p0: Event, p1: Event): Boolean {
return p0.eventId == p1.eventId
}
override fun areContentsTheSame(p0: Event, p1: Event): Boolean {
return p0 == p1
}
}

View file

@ -14,10 +14,10 @@ import im.vector.matrix.android.api.session.room.Room
import im.vector.riotredesign.R
import im.vector.riotredesign.core.platform.RiotFragment
import im.vector.riotredesign.core.utils.FragmentArgumentDelegate
import kotlinx.android.synthetic.main.fragment_room_list.*
import kotlinx.android.synthetic.main.fragment_room_detail.*
import org.koin.android.ext.android.inject
class RoomDetailFragment : RiotFragment() {
class RoomDetailFragment : RiotFragment(), TimelineAdapter.Callback {
companion object {
@ -31,7 +31,7 @@ class RoomDetailFragment : RiotFragment() {
private val matrix by inject<Matrix>()
private val currentSession = matrix.currentSession!!
private var roomId by FragmentArgumentDelegate<String>()
private val timelineController = TimelineEventController()
private val adapter = TimelineAdapter(this)
private lateinit var room: Room
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -46,14 +46,27 @@ class RoomDetailFragment : RiotFragment() {
}
private fun renderEvents(events: PagedList<Event>?) {
timelineController.submitList(events)
adapter.submitList(events)
}
private fun setupRecyclerView() {
val linearLayoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
linearLayoutManager.stackFromEnd = true
epoxyRecyclerView.layoutManager = linearLayoutManager
epoxyRecyclerView.setController(timelineController)
val layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
if (layoutManager.findLastCompletelyVisibleItemPosition() == positionStart - itemCount) {
layoutManager.scrollToPosition(adapter.itemCount - 1)
}
}
})
recyclerView.layoutManager = layoutManager
recyclerView.adapter = adapter
recyclerView.setHasFixedSize(true)
}
override fun onEventsListChanged(oldList: List<Event>?, newList: List<Event>?) {
if (oldList == null && newList != null) {
recyclerView.scrollToPosition(newList.size - 1)
}
}

View file

@ -0,0 +1,57 @@
package im.vector.riotredesign.features.home
import android.arch.paging.PagedList
import android.arch.paging.PagedListAdapter
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.riotredesign.R
/**
* Created by francois on 14/05/2018.
*/
class TimelineAdapter(private val callback: Callback? = null)
: PagedListAdapter<Event, TimelineAdapter.ViewHolder>(EventDiffUtilCallback()) {
private var currentList: List<Event>? = null
override fun onCreateViewHolder(parent: ViewGroup, position: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_event, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
val event = getItem(position)
viewHolder.bind(event)
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val titleView = view.findViewById<TextView>(R.id.titleView)!!
fun bind(event: Event?) {
if (event == null) {
} else {
titleView.text = event.toString()
}
}
}
override fun onCurrentListChanged(newList: PagedList<Event>?) {
callback?.onEventsListChanged(currentList, newList)
currentList = newList
}
interface Callback {
fun onEventsListChanged(oldList: List<Event>?, newList: List<Event>?)
}
}

View file

@ -6,7 +6,6 @@ import com.airbnb.epoxy.paging.PagedListEpoxyController
import im.vector.matrix.android.api.session.events.model.Event
class TimelineEventController : PagedListEpoxyController<Event>(
modelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler(),
diffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
) {

View file

@ -11,13 +11,14 @@
android:id="@+id/loginField"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:hint="Name"
android:inputType="textPersonName"
android:inputType="text"
android:singleLine="false"
android:text="ganfra07086"
app:layout_constraintBottom_toTopOf="@+id/passwordField"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
@ -32,6 +33,7 @@
android:ems="10"
android:hint="Password"
android:inputType="textPassword"
android:text="111111"
app:layout_constraintEnd_toEndOf="@+id/loginField"
app:layout_constraintStart_toStartOf="@+id/loginField"
app:layout_constraintTop_toBottomOf="@+id/loginField" />
@ -40,10 +42,10 @@
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@ -55,9 +57,9 @@
android:id="@+id/authenticateButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="32dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="8dp"
android:text="Authenticate"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"

View file

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.airbnb.epoxy.EpoxyRecyclerView
android:id="@+id/epoxyRecyclerView"
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View file

@ -7,7 +7,10 @@ import io.realm.RealmQuery
import io.realm.RealmResults
fun ChunkEntity.Companion.where(realm: Realm, roomId: String): RealmQuery<ChunkEntity> {
return realm.where(ChunkEntity::class.java).equalTo("room.roomId", roomId)
return realm.where(ChunkEntity::class.java)
.equalTo("room.roomId", roomId)
.notEqualTo("prevToken", DBConstants.STATE_EVENTS_CHUNK_TOKEN)
.notEqualTo("nextToken", DBConstants.STATE_EVENTS_CHUNK_TOKEN)
}
fun ChunkEntity.Companion.findWithPrevToken(realm: Realm, roomId: String, prevToken: String?): ChunkEntity? {

View file

@ -25,13 +25,19 @@ data class DefaultRoom(
override fun liveTimeline(): LiveData<PagedList<Event>> {
val realmDataSourceFactory = monarchy.createDataSourceFactory { realm ->
ChunkEntity.where(realm, roomId).findAll().last(null).let { it?.events }?.where()
ChunkEntity.where(realm, roomId)
.findAll()
.last(null)
?.let { it.events }
?.where()
?.sort("originServerTs")
}
val domainSourceFactory = realmDataSourceFactory.map { EventMapper.map(it) }
val pagedListConfig = PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPageSize(10)
.setInitialLoadSizeHint(30)
.setPrefetchDistance(5)
.build()

View file

@ -9,7 +9,6 @@ import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.database.mapper.asEntity
import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
import im.vector.matrix.android.internal.database.query.findWithNextToken
@ -87,34 +86,30 @@ class PaginationRequest(private val roomAPI: RoomAPI,
ChunkEntity()
}
val eventsToAdd = ArrayList<EventEntity>()
currentChunk.prevToken = chunkEvent.prevToken
mergedEvents.forEach { event ->
val eventEntity = event.asEntity().let {
realm.copyToRealmOrUpdate(it)
}
if (!currentChunk.events.contains(eventEntity)) {
eventsToAdd.add(0, eventEntity)
currentChunk.events.add(0, eventEntity)
}
}
if (prevChunk != null) {
eventsToAdd.addAll(0, prevChunk.events)
currentChunk.events.addAll(prevChunk.events)
roomEntity.chunks.remove(prevChunk)
} else if (hasOverlapped) {
chunksOverlapped.forEach { chunk ->
chunk.events.forEach { event ->
if (!currentChunk.events.contains(event)) {
eventsToAdd.add(0, event)
currentChunk.events.add(0, event)
}
}
roomEntity.chunks.remove(chunk)
}
}
currentChunk.events.addAll(0, eventsToAdd)
if (!roomEntity.chunks.contains(currentChunk)) {
roomEntity.chunks.add(currentChunk)
}

View file

@ -26,7 +26,15 @@ class TimelineBoundaryCallback(private val paginationRequest: PaginationRequest,
}
override fun onItemAtEndLoaded(itemAtEnd: Event) {
//Todo handle forward pagination
helper.runIfNotRunning(PagingRequestHelper.RequestType.AFTER) {
monarchy.doWithRealm { realm ->
if (itemAtEnd.eventId == null) {
return@doWithRealm
}
val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtEnd.eventId)).firstOrNull()
paginationRequest.execute(roomId, chunkEntity?.nextToken, PaginationDirection.FORWARDS, callback = createCallback(it))
}
}
}
override fun onItemAtFrontLoaded(itemAtFront: Event) {
@ -39,7 +47,6 @@ class TimelineBoundaryCallback(private val paginationRequest: PaginationRequest,
paginationRequest.execute(roomId, chunkEntity?.prevToken, PaginationDirection.BACKWARDS, callback = createCallback(it))
}
}
}
private fun createCallback(pagingRequestCallback: PagingRequestHelper.Request.Callback) = object : MatrixCallback<TokenChunkEvent> {