diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 998ced45..15da4cd7 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/src/main/java/im/vector/riotredesign/features/home/EventDiffUtilCallback.kt b/app/src/main/java/im/vector/riotredesign/features/home/EventDiffUtilCallback.kt new file mode 100644 index 00000000..fa5adb2b --- /dev/null +++ b/app/src/main/java/im/vector/riotredesign/features/home/EventDiffUtilCallback.kt @@ -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() { + override fun areItemsTheSame(p0: Event, p1: Event): Boolean { + return p0.eventId == p1.eventId + } + + override fun areContentsTheSame(p0: Event, p1: Event): Boolean { + return p0 == p1 + } +} \ No newline at end of file diff --git a/app/src/main/java/im/vector/riotredesign/features/home/RoomDetailFragment.kt b/app/src/main/java/im/vector/riotredesign/features/home/RoomDetailFragment.kt index 6eb5259d..8d601a60 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/RoomDetailFragment.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/RoomDetailFragment.kt @@ -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() private val currentSession = matrix.currentSession!! private var roomId by FragmentArgumentDelegate() - 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?) { - 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?, newList: List?) { + if (oldList == null && newList != null) { + recyclerView.scrollToPosition(newList.size - 1) + } } diff --git a/app/src/main/java/im/vector/riotredesign/features/home/TimelineAdapter.kt b/app/src/main/java/im/vector/riotredesign/features/home/TimelineAdapter.kt new file mode 100644 index 00000000..f8c3a39e --- /dev/null +++ b/app/src/main/java/im/vector/riotredesign/features/home/TimelineAdapter.kt @@ -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(EventDiffUtilCallback()) { + + + private var currentList: List? = 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(R.id.titleView)!! + + fun bind(event: Event?) { + if (event == null) { + + } else { + titleView.text = event.toString() + } + } + } + + override fun onCurrentListChanged(newList: PagedList?) { + callback?.onEventsListChanged(currentList, newList) + currentList = newList + } + + interface Callback { + fun onEventsListChanged(oldList: List?, newList: List?) + } + +} + diff --git a/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventController.kt b/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventController.kt index ac4ff1bf..bb19f9a2 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventController.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventController.kt @@ -6,7 +6,6 @@ import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.matrix.android.api.session.events.model.Event class TimelineEventController : PagedListEpoxyController( - modelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler(), diffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler() ) { diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index c8984e15..18563d22 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -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" diff --git a/app/src/main/res/layout/fragment_room_detail.xml b/app/src/main/res/layout/fragment_room_detail.xml index a8c7d0e0..7d8b00af 100644 --- a/app/src/main/res/layout/fragment_room_detail.xml +++ b/app/src/main/res/layout/fragment_room_detail.xml @@ -1,10 +1,10 @@ - - diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt index aa975c1d..b722f647 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt @@ -7,7 +7,10 @@ import io.realm.RealmQuery import io.realm.RealmResults fun ChunkEntity.Companion.where(realm: Realm, roomId: String): RealmQuery { - 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? { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt index 21cca576..c213856c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt @@ -25,13 +25,19 @@ data class DefaultRoom( override fun liveTimeline(): LiveData> { 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() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt index 1a2c0d53..199ea536 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt @@ -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() - 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) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt index dc1c6a1f..5395609e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt @@ -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 {