From ccec19e88ae36970613ccd21d579589401970a3a Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Sun, 1 Apr 2018 21:44:08 +0200
Subject: [PATCH] Attempt at improving message loading performance

---
 .../ui/chat/messages/MessageListFragment.kt   | 24 +++++++----
 .../kuschku/libquassel/ConnectionUnitTest.kt  |  2 +-
 .../persistence/QuasselDatabase.kt            | 40 ++++++++++++++++++-
 .../viewmodel/QuasselViewModel.kt             |  2 +-
 4 files changed, 58 insertions(+), 10 deletions(-)

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 fe5e21bec..e6c3e77b4 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
@@ -231,6 +231,21 @@ class MessageListFragment : ServiceBoundFragment() {
         }
       })
 
+    fun processMessages(list: List<QuasselDatabase.DatabaseMessage>, selected: Set<MsgId>,
+                        expanded: Set<MsgId>, markerLine: MsgId?): List<DisplayMessage> {
+      var previous: QuasselDatabase.DatabaseMessage? = null
+      return list.asReversed().map {
+        it.followUp = previous?.sender == it.sender
+        previous = it
+        DisplayMessage(
+          content = it,
+          isSelected = selected.contains(it.messageId),
+          isExpanded = expanded.contains(it.messageId),
+          isMarkerLine = markerLine == it.messageId
+        )
+      }.asReversed()
+    }
+
     val data = combineLatest(viewModel.buffer,
                              viewModel.selectedMessages,
                              viewModel.expandedMessages,
@@ -238,13 +253,8 @@ class MessageListFragment : ServiceBoundFragment() {
       .toLiveData().switchMapNotNull { (buffer, selected, expanded, markerLine) ->
         database.filtered().listen(accountId, buffer).switchMapNotNull { filtered ->
           LivePagedListBuilder(
-            database.message().findByBufferIdPagedWithDayChange(buffer, filtered).map {
-              DisplayMessage(
-                content = it,
-                isSelected = selected.contains(it.messageId),
-                isExpanded = expanded.contains(it.messageId),
-                isMarkerLine = markerLine.orNull() == it.messageId
-              )
+            database.message().findByBufferIdPagedWithDayChange(buffer, filtered).mapByPage {
+              processMessages(it, selected.keys, expanded, markerLine.orNull())
             },
             PagedList.Config.Builder()
               .setPageSize(backlogSettings.pageSize)
diff --git a/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt b/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt
index bd816b742..8d7514cb8 100644
--- a/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt
@@ -54,4 +54,4 @@ class ConnectionUnitTest {
     }, user to pass, {}, {})
     session.join()
   }
-}
\ No newline at end of file
+}
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 df1f595d5..a72a63436 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
@@ -201,6 +201,44 @@ fun QuasselDatabase.MessageDao.clearMessages(
 fun QuasselDatabase.MessageDao.findByBufferIdPagedWithDayChange(bufferId: Int, type: Int) =
   this.findMessagesRawPaged(SimpleSQLiteQuery("""
 SELECT t.*
+FROM
+  (
+    SELECT
+      messageId,
+      time,
+      type,
+      flag,
+      bufferId,
+      sender,
+      senderPrefixes,
+      content,
+      followUp
+    FROM message
+    WHERE bufferId = ?
+          AND type & ~? > 0
+    UNION ALL
+    SELECT DISTINCT
+      strftime('%s', date(datetime(time / 1000, 'unixepoch', 'localtime')), 'utc') * -1000 AS messageId,
+      strftime('%s', date(datetime(time / 1000, 'unixepoch', 'localtime')), 'utc') * 1000  AS time,
+      8192                                                                                 AS type,
+      0                                                                                    AS flag,
+      ?                                                                                    AS bufferId,
+      ''                                                                                   AS sender,
+      ''                                                                                   AS senderPrefixes,
+      ''                                                                                   AS content,
+      0                                                                                    AS followUp
+    FROM message
+    WHERE bufferId = ?
+          AND type & ~? > 0
+  ) t
+ORDER BY TIME
+  DESC, messageId
+  DESC
+  """, arrayOf(bufferId, type, bufferId, bufferId, type)))
+
+fun QuasselDatabase.MessageDao.findByBufferIdPagedWithDayChangeSlow(bufferId: Int, type: Int) =
+  this.findMessagesRawPaged(SimpleSQLiteQuery("""
+SELECT t.*
 FROM
   (
     SELECT
@@ -248,4 +286,4 @@ FROM
 ORDER BY TIME
   DESC, messageId
   DESC
-  """, arrayOf(bufferId, type, bufferId, type, bufferId, bufferId, type)))
\ No newline at end of file
+  """, arrayOf(bufferId, type, bufferId, type, bufferId, bufferId, type)))
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
index 4d3b89ce7..93e54b335 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
@@ -37,7 +37,7 @@ class QuasselViewModel : ViewModel() {
     return result.isNotEmpty()
   }
 
-  val expandedMessages = BehaviorSubject.createDefault(emptyList<MsgId>())
+  val expandedMessages = BehaviorSubject.createDefault(emptySet<MsgId>())
 
   val buffer = BehaviorSubject.createDefault(-1)
   val buffer_liveData = buffer.toLiveData()
-- 
GitLab