From 583e7ea17abbc61d0b7ea169e656bccd52514c4f Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Tue, 12 Jun 2018 22:26:40 +0200
Subject: [PATCH] Fixes several major causes of slowdown

---
 .../quasseldroid/ui/chat/ChatActivity.kt      | 11 +++-----
 .../quassel/syncables/IrcChannel.kt           | 27 ++++++++++++++-----
 .../viewmodel/QuasselViewModel.kt             | 10 +++----
 .../quasseldroid/viewmodel/data/BufferData.kt |  3 ++-
 4 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
index 09fdfcc61..8223f9825 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
@@ -585,7 +585,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
     })
 
     // Only show nick list when we’re in a channel buffer
-    viewModel.bufferData.distinctUntilChanged().toLiveData().observe(this, Observer {
+    viewModel.bufferData.toLiveData().observe(this, Observer {
       bufferData = it
       if (bufferData?.info?.type?.hasFlag(Buffer_Type.ChannelBuffer) == true) {
         drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.END)
@@ -700,12 +700,9 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
        bufferData?.info?.type?.hasFlag(Buffer_Type.QueryBuffer) ?: false) &&
       Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
     menu?.retint(toolbar.context)
-    viewModel.nickData.toLiveData().observe(this, Observer {
-      val count = it?.count() ?: 0
-      menu?.findItem(R.id.action_nicklist)?.icon = NickCountDrawable(count,
-                                                                     nickCountDrawableSize,
-                                                                     nickCountDrawableColor)
-    })
+    menu?.findItem(R.id.action_nicklist)?.icon = NickCountDrawable(bufferData?.userCount ?: 0,
+                                                                   nickCountDrawableSize,
+                                                                   nickCountDrawableColor)
     return super.onCreateOptionsMenu(menu)
   }
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
index 418e7f505..543925d72 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
@@ -140,6 +140,8 @@ class IrcChannel(
     _userModes.getOr(ircUser, "")
   }
 
+  fun userCount() = _userCount
+
   fun userModes(): Map<IrcUser, String> = _userModes
   fun userModes(nick: String) = network().ircUser(nick)?.let { userModes(it) } ?: ""
   fun liveUserModes(nick: String) = network().ircUser(nick)?.let { userModes(it) } ?: ""
@@ -256,7 +258,7 @@ class IrcChannel(
       _userModes[user] = modes
       user.joinChannel(this, true)
     }
-    live_userModes.onNext(_userModes)
+    updateUsers()
   }
 
   override fun joinIrcUser(ircuser: IrcUser) {
@@ -278,7 +280,7 @@ class IrcChannel(
       network().removeIrcChannel(this)
       proxy.stopSynchronize(this)
     }
-    live_userModes.onNext(_userModes)
+    updateUsers()
   }
 
   override fun part(nick: String) {
@@ -289,7 +291,7 @@ class IrcChannel(
     if (ircuser == null || !isKnownUser(ircuser))
       return
     _userModes[ircuser] = modes
-    live_userModes.onNext(_userModes)
+    updateUsers()
   }
 
   override fun setUserModes(nick: String, modes: String) {
@@ -306,7 +308,7 @@ class IrcChannel(
     if (_userModes.getOr(ircuser, "").contains(mode, ignoreCase = true))
       return
     _userModes[ircuser] = _userModes.getOr(ircuser, "") + mode
-    live_userModes.onNext(_userModes)
+    updateUsers()
   }
 
   override fun addUserMode(nick: String, mode: String) {
@@ -320,7 +322,7 @@ class IrcChannel(
       return
     _userModes[ircuser] = _userModes.getOr(ircuser, "")
       .replace(mode, "", ignoreCase = true)
-    live_userModes.onNext(_userModes)
+    updateUsers()
   }
 
   override fun removeUserMode(nick: String, mode: String) {
@@ -368,6 +370,12 @@ class IrcChannel(
       live_updates.onNext(Unit)
     }
 
+  private var _userCount: Int = 0
+    set(value) {
+      field = value
+      live_updates.onNext(Unit)
+    }
+
   private var _topic: String = ""
     set(value) {
       field = value
@@ -386,10 +394,17 @@ class IrcChannel(
       live_updates.onNext(Unit)
     }
 
+  private fun updateUsers() {
+    _userCount = _userModes.size
+    live_userModes.onNext(_userModes)
+  }
+
   private val live_userModes = BehaviorSubject.createDefault(mutableMapOf<IrcUser, String>())
   private var _userModes: MutableMap<IrcUser, String>
     get() = live_userModes.value
-    set(value) = live_userModes.onNext(value)
+    set(value) {
+      updateUsers()
+    }
 
   private var _network: Network = network
 
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 2c12beb4a..17e9e0e0a 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
@@ -176,7 +176,8 @@ class QuasselViewModel : ViewModel() {
                     BufferData(
                       info = info,
                       network = network,
-                      description = it.topic()
+                      description = it.topic(),
+                      userCount = it.userCount()
                     )
                   }
                 }
@@ -201,7 +202,7 @@ class QuasselViewModel : ViewModel() {
     } else {
       Observable.just(BufferData())
     }
-  }
+  }.distinctUntilChanged().throttleLast(100, TimeUnit.MILLISECONDS)
 
   val nickData: Observable<List<IrcUserItem>> = combineLatest(session, buffer)
     .switchMap { (sessionOptional, buffer) ->
@@ -242,7 +243,7 @@ class QuasselViewModel : ViewModel() {
       } else {
         Observable.just(emptyList())
       }
-    }
+    }.distinctUntilChanged().throttleLast(100, TimeUnit.MILLISECONDS)
 
   val bufferViewConfigs = bufferViewManager.mapSwitchMap { manager ->
     manager.liveBufferViewConfigs().map { ids ->
@@ -331,7 +332,6 @@ class QuasselViewModel : ViewModel() {
         if (bufferSyncer != null && config != null) {
           session.liveNetworks().switchMap { networks ->
             config.liveUpdates()
-              .debounce(16, TimeUnit.MILLISECONDS)
               .switchMap { currentConfig ->
                 combineLatest<Collection<BufferId>>(
                   listOf(
@@ -517,5 +517,5 @@ class QuasselViewModel : ViewModel() {
         } else {
           Observable.just(Pair<BufferViewConfig?, List<BufferProps>>(null, emptyList()))
         }
-      }
+      }.distinctUntilChanged().throttleLast(100, TimeUnit.MILLISECONDS)
 }
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/BufferData.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/BufferData.kt
index f3a175577..700c453f1 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/BufferData.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/BufferData.kt
@@ -25,5 +25,6 @@ import de.kuschku.libquassel.quassel.syncables.Network
 data class BufferData(
   val info: BufferInfo? = null,
   val network: Network? = null,
-  val description: String? = null
+  val description: String? = null,
+  val userCount: Int = 0
 )
-- 
GitLab