From 452aa9b666ad971774436c21479762078369d2de Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Wed, 6 Jun 2018 16:06:29 +0200
Subject: [PATCH] Implement fast scroll for messages

---
 .../ui/chat/messages/MessageAdapter.kt            | 11 ++++++++++-
 .../ui/chat/messages/MessageListFragment.kt       | 15 ++++++---------
 app/src/main/res/layout/fragment_messages.xml     |  4 ++--
 .../quasseldroid/persistence/QuasselDatabase.kt   |  2 +-
 4 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
index 2593a6037..e7f13c555 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
@@ -31,6 +31,7 @@ import android.widget.ImageView
 import android.widget.TextView
 import butterknife.BindView
 import butterknife.ButterKnife
+import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
 import de.kuschku.libquassel.protocol.Message_Flag
 import de.kuschku.libquassel.protocol.Message_Type
 import de.kuschku.libquassel.util.flag.hasFlag
@@ -43,6 +44,9 @@ import de.kuschku.quasseldroid.util.helper.visibleIf
 import de.kuschku.quasseldroid.util.ui.BetterLinkMovementMethod
 import de.kuschku.quasseldroid.util.ui.DoubleClickHelper
 import de.kuschku.quasseldroid.viewmodel.data.FormattedMessage
+import org.threeten.bp.ZoneId
+import org.threeten.bp.format.DateTimeFormatter
+import org.threeten.bp.format.FormatStyle
 import javax.inject.Inject
 
 class MessageAdapter @Inject constructor(
@@ -54,7 +58,12 @@ class MessageAdapter @Inject constructor(
 
     override fun areContentsTheSame(oldItem: DisplayMessage, newItem: DisplayMessage) =
       oldItem == newItem
-  }) {
+  }), FastScrollRecyclerView.SectionedAdapter {
+  private val dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
+
+  override fun getSectionName(position: Int) =
+    getItem(position)?.content?.time?.atZone(ZoneId.systemDefault())?.format(dateFormatter) ?: ""
+
   private val movementMethod = BetterLinkMovementMethod.newInstance()
   private var clickListener: ((FormattedMessage) -> Unit)? = null
   private var longClickListener: ((FormattedMessage) -> Unit)? = null
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
index 0bfa0ba75..16ae92bc1 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
@@ -197,10 +197,8 @@ class MessageListFragment : ServiceBoundFragment() {
 
   private val boundaryCallback = object :
     PagedList.BoundaryCallback<DisplayMessage>() {
-    override fun onItemAtFrontLoaded(itemAtFront: DisplayMessage) = Unit
-    override fun onItemAtEndLoaded(itemAtEnd: DisplayMessage) {
-      loadMore()
-    }
+    override fun onItemAtFrontLoaded(itemAtFront: DisplayMessage) = loadMore()
+    override fun onItemAtEndLoaded(itemAtEnd: DisplayMessage) = Unit
   }
 
   override fun onCreateView(
@@ -211,7 +209,6 @@ class MessageListFragment : ServiceBoundFragment() {
     ButterKnife.bind(this, view)
 
     linearLayoutManager = LinearLayoutManager(context)
-    linearLayoutManager.reverseLayout = true
 
     backlogRequester = BacklogRequester(viewModel, database)
 
@@ -290,7 +287,7 @@ class MessageListFragment : ServiceBoundFragment() {
                         expanded: Set<MsgId>, markerLine: MsgId?): List<DisplayMessage> {
       var previous: QuasselDatabase.MessageData? = null
       var previousDate: ZonedDateTime? = null
-      return list.mapReverse {
+      return list.map {
         val date = it.time.atZone(ZoneId.systemDefault()).truncatedTo(ChronoUnit.DAYS)
         val isSameDay = previousDate?.isEqual(date) ?: false
         val isFollowUp = previous?.sender == it.sender && previous?.type == it.type && isSameDay
@@ -374,8 +371,8 @@ class MessageListFragment : ServiceBoundFragment() {
     })
 
     fun checkScroll() {
-      if (linearLayoutManager.findFirstVisibleItemPosition() < 2 && !isScrolling) {
-        messageList.scrollToPosition(0)
+      if (linearLayoutManager.findLastVisibleItemPosition() > linearLayoutManager.itemCount - 2 && !isScrolling) {
+        messageList.scrollToPosition(linearLayoutManager.itemCount - 1)
       }
     }
 
@@ -410,7 +407,7 @@ class MessageListFragment : ServiceBoundFragment() {
         fab.visibility = View.VISIBLE
       }
     })
-    scrollDown.setOnClickListener { messageList.scrollToPosition(0) }
+    scrollDown.setOnClickListener { messageList.scrollToPosition(linearLayoutManager.itemCount - 1) }
 
     savedInstanceState?.run {
       messageList.layoutManager.onRestoreInstanceState(getParcelable(KEY_STATE_LIST))
diff --git a/app/src/main/res/layout/fragment_messages.xml b/app/src/main/res/layout/fragment_messages.xml
index 93d165165..3efb80076 100644
--- a/app/src/main/res/layout/fragment_messages.xml
+++ b/app/src/main/res/layout/fragment_messages.xml
@@ -30,11 +30,11 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <android.support.v7.widget.RecyclerView
+    <com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
       android:id="@+id/messages"
+      style="@style/Widget.FastScroller"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
-      android:scrollbars="vertical"
       app:stackFromEnd="true"
       tools:listitem="@layout/widget_chatmessage_plain" />
 
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
index 7a6433b8a..6fc4a28b6 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
@@ -93,7 +93,7 @@ abstract class QuasselDatabase : RoomDatabase() {
     @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC")
     fun findByBufferId(bufferId: Int): List<MessageData>
 
-    @Query("SELECT * FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0 ORDER BY messageId DESC")
+    @Query("SELECT * FROM message WHERE bufferId = :bufferId AND type & ~ :type > 0 AND ignored = 0 ORDER BY messageId ASC")
     fun findByBufferIdPaged(bufferId: Int, type: Int): DataSource.Factory<Int, MessageData>
 
     @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1")
-- 
GitLab