From 89331293dfeb39e11c60f9b7e39a1e75cb386774 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Wed, 25 Apr 2018 01:56:42 +0200
Subject: [PATCH] Further improvements, bugfixes, and cleanup

Signed-off-by: Janne Koschinski <janne@kuschku.de>
---
 .../aliaslist/AliasListFragment.kt            |   2 +-
 .../chatlist/ChatListBaseFragment.kt          |   3 +-
 .../highlightlist/HighlightListFragment.kt    |   4 +-
 .../identity/IdentityBaseFragment.kt          |   3 +-
 .../ignorelist/IgnoreListFragment.kt          |   2 +-
 .../network/NetworkBaseFragment.kt            |   3 +-
 .../util/ui/RipplePassthroughTextView.kt      |   4 +-
 app/src/main/res/layout/layout_history.xml    |   4 +-
 app/src/main/res/layout/widget_network.xml    |   4 +-
 app/src/main/res/values/strings_licenses.xml  |   2 +-
 .../message/ClientInitAckSerializer.kt        |   2 +-
 .../quassel/syncables/AliasManager.kt         |  16 +-
 .../quassel/syncables/BufferViewConfig.kt     |  45 ++---
 .../quassel/syncables/HighlightRuleManager.kt |  23 +--
 .../libquassel/quassel/syncables/Identity.kt  |  62 ++-----
 .../quassel/syncables/IgnoreListManager.kt    |  16 +-
 .../libquassel/quassel/syncables/Network.kt   |  82 +++------
 .../quassel/syncables/NetworkConfig.kt        |  39 +---
 .../de/kuschku/libquassel/util/Optional.kt    |   2 +-
 .../serializer/BufferInfoSerializerTest.kt    |   6 +-
 .../quassel/syncables/AliasManagerTest.kt     |   5 +-
 .../quassel/syncables/BufferViewConfigTest.kt |   5 +-
 .../syncables/HighlightRuleManagerTest.kt     |   5 +-
 .../quassel/syncables/IdentityTest.kt         |   5 +-
 .../syncables/IgnoreListManagerTest.kt        |   5 +-
 .../quassel/syncables/NetworkConfigTest.kt    |   5 +-
 .../quassel/syncables/NetworkTest.kt          |   5 +-
 .../slidinguppanel/SlidingUpPanelLayout.java  | 166 ++++++++++--------
 28 files changed, 181 insertions(+), 344 deletions(-)

diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliaslist/AliasListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliaslist/AliasListFragment.kt
index 0056c278a..7c6443c7c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliaslist/AliasListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/aliaslist/AliasListFragment.kt
@@ -136,7 +136,7 @@ class AliasListFragment : SettingsFragment(), SettingsFragment.Savable,
 
   override fun hasChanged() = aliasManager?.let { (it, data) ->
     applyChanges(data)
-    data != it
+    !data.isEqual(it)
   } ?: false
 
   private fun applyChanges(data: AliasManager) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
index fd2b6965f..b8d7547fa 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
@@ -179,8 +179,7 @@ abstract class ChatListBaseFragment : SettingsFragment(), SettingsFragment.Savab
 
   override fun hasChanged() = chatlist?.let { (it, data) ->
     applyChanges(data, it)
-
-    data != it
+    it == null || !data.isEqual(it)
   } ?: true
 
   protected fun applyChanges(data: BufferViewConfig, old: BufferViewConfig?) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightlist/HighlightListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightlist/HighlightListFragment.kt
index 8c7e4620e..7b24e1e84 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightlist/HighlightListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/highlightlist/HighlightListFragment.kt
@@ -211,8 +211,8 @@ class HighlightListFragment : SettingsFragment(), SettingsFragment.Savable,
 
   override fun hasChanged() = ruleManager?.let { (it, data) ->
     applyChanges(data)
-    data != it
-  } ?: false
+    !data.isEqual(it)
+  } == true
 
   private fun applyChanges(data: HighlightRuleManager) {
     data.setHighlightNick(highlightNickType.selectedItemId.toInt())
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
index 9a27d8cce..f2b7eef99 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
@@ -168,8 +168,7 @@ abstract class IdentityBaseFragment : SettingsFragment(), SettingsFragment.Savab
 
   override fun hasChanged() = identity?.let { (it, data) ->
     applyChanges(data)
-
-    data != it
+    it == null || !data.isEqual(it)
   } ?: true
 
   protected fun applyChanges(data: Identity) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
index 32739c2e8..31d39c181 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/ignorelist/IgnoreListFragment.kt
@@ -127,7 +127,7 @@ class IgnoreListFragment : SettingsFragment(), SettingsFragment.Savable,
 
   override fun hasChanged() = ignoreListManager?.let { (it, data) ->
     applyChanges(data)
-    data != it
+    !data.isEqual(it)
   } ?: false
 
   private fun applyChanges(data: IgnoreListManager) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
index 3e75f0e40..d589bb0a7 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
@@ -259,8 +259,7 @@ abstract class NetworkBaseFragment : SettingsFragment(), SettingsFragment.Savabl
 
   override fun hasChanged() = network?.let { (it, data) ->
     applyChanges(data)
-
-    data != it
+    it == null || !data.isEqual(it)
   } ?: true
 
   protected fun applyChanges(data: Network) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/RipplePassthroughTextView.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/RipplePassthroughTextView.kt
index 1da8bca8b..5e0794218 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/RipplePassthroughTextView.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/RipplePassthroughTextView.kt
@@ -23,12 +23,12 @@
 package de.kuschku.quasseldroid.util.ui
 
 import android.content.Context
+import android.support.v7.widget.AppCompatTextView
 import android.text.Spannable
 import android.util.AttributeSet
 import android.view.MotionEvent
-import android.widget.TextView
 
-class RipplePassthroughTextView : TextView {
+class RipplePassthroughTextView : AppCompatTextView {
   constructor(context: Context?) : super(context)
   constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
   constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) :
diff --git a/app/src/main/res/layout/layout_history.xml b/app/src/main/res/layout/layout_history.xml
index ebd9300a7..d9c462652 100644
--- a/app/src/main/res/layout/layout_history.xml
+++ b/app/src/main/res/layout/layout_history.xml
@@ -20,7 +20,7 @@
   ~ with this program.  If not, see <http://www.gnu.org/licenses/>.
   -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/card_panel"
@@ -82,4 +82,4 @@
         tools:listitem="@layout/widget_history_message" />
     </LinearLayout>
   </android.support.v7.widget.CardView>
-</FrameLayout>
+</merge>
diff --git a/app/src/main/res/layout/widget_network.xml b/app/src/main/res/layout/widget_network.xml
index 1ce22e4ee..207c998c8 100644
--- a/app/src/main/res/layout/widget_network.xml
+++ b/app/src/main/res/layout/widget_network.xml
@@ -55,7 +55,7 @@
       android:textSize="14sp"
       tools:text="Freenode" />
 
-    <ImageView
+    <android.support.v7.widget.AppCompatImageView
       android:id="@+id/status"
       android:layout_width="wrap_content"
       android:layout_height="match_parent"
@@ -68,7 +68,7 @@
       android:paddingStart="16dp"
       android:paddingTop="12dp"
       android:scaleType="fitEnd"
-      android:tint="?attr/colorTextSecondary"
+      app:tint="?attr/colorTextSecondary"
       app:srcCompat="@drawable/ic_chevron_down" />
   </LinearLayout>
 </LinearLayout>
diff --git a/app/src/main/res/values/strings_licenses.xml b/app/src/main/res/values/strings_licenses.xml
index 2f55c55d3..114aa80c5 100644
--- a/app/src/main/res/values/strings_licenses.xml
+++ b/app/src/main/res/values/strings_licenses.xml
@@ -104,7 +104,7 @@
     <p><strong>4. Restrictions.</strong>The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:</p>
     <p>a. You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(c), as requested.</p>
     <p>b. You may Distribute or Publicly Perform an Adaptation only under the terms of: (i) this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible License. If you license the Adaptation under one of the licenses mentioned in (iv), you must comply with the terms of that license. If you license the Adaptation under the terms of any of the licenses mentioned in (i), (ii) or (iii) (the "Applicable License"), you must comply with the terms of the Applicable License generally and the following provisions: (I) You must include a copy of, or the URI for, the Applicable License with every copy of each Adaptation You Distribute or Publicly Perform; (II) You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License; (III) You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform; (IV) when You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License.</p>
-    <p>c. If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.</p>
+    <p>c. If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor\'s copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.</p>
     <p>d. Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.</p>
     <p><strong>5. Representations, Warranties and Disclaimer</strong></p>
     <p>UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.</p>
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/message/ClientInitAckSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/message/ClientInitAckSerializer.kt
index 7c7c43121..9764151e2 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/message/ClientInitAckSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/message/ClientInitAckSerializer.kt
@@ -36,7 +36,7 @@ object ClientInitAckSerializer : HandshakeMessageSerializer<HandshakeMessage.Cli
   )
 
   override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInitAck(
-    coreFeatures = Flags.Companion.of(data["CoreFeatures"].value(0)),
+    coreFeatures = Flags.of(data["CoreFeatures"].value(0)),
     backendInfo = data["StorageBackends"].value(),
     authenticatorInfo = data["Authenticators"].value(),
     coreConfigured = data["Configured"].value(),
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/AliasManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/AliasManager.kt
index a928e38c0..e314f104d 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/AliasManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/AliasManager.kt
@@ -193,20 +193,8 @@ class AliasManager constructor(
 
   private var _aliases = listOf<IAliasManager.Alias>()
 
-  override fun equals(other: Any?): Boolean {
-    if (this === other) return true
-    if (javaClass != other?.javaClass) return false
-
-    other as AliasManager
-
-    if (_aliases != other._aliases) return false
-
-    return true
-  }
-
-  override fun hashCode(): Int {
-    return _aliases.hashCode()
-  }
+  fun isEqual(other: AliasManager): Boolean =
+    this.aliasList() == other.aliasList()
 
   override fun toString(): String {
     return "AliasManager(_aliases=$_aliases)"
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
index 0d4eb1a29..c294c9ac8 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
@@ -350,41 +350,16 @@ class BufferViewConfig constructor(
     }
   }
 
-  override fun equals(other: Any?): Boolean {
-    if (this === other) return true
-    if (javaClass != other?.javaClass) return false
-
-    other as BufferViewConfig
-
-    if (_bufferViewId != other._bufferViewId) return false
-    if (_bufferViewName != other._bufferViewName) return false
-    if (_networkId != other._networkId) return false
-    if (_addNewBuffersAutomatically != other._addNewBuffersAutomatically) return false
-    if (_sortAlphabetically != other._sortAlphabetically) return false
-    if (_hideInactiveBuffers != other._hideInactiveBuffers) return false
-    if (_hideInactiveNetworks != other._hideInactiveNetworks) return false
-    if (_disableDecoration != other._disableDecoration) return false
-    if (_allowedBufferTypes != other._allowedBufferTypes) return false
-    if (_minimumActivity != other._minimumActivity) return false
-    if (_showSearch != other._showSearch) return false
-
-    return true
-  }
-
-  override fun hashCode(): Int {
-    var result = _bufferViewId
-    result = 31 * result + _bufferViewName.hashCode()
-    result = 31 * result + _networkId
-    result = 31 * result + _addNewBuffersAutomatically.hashCode()
-    result = 31 * result + _sortAlphabetically.hashCode()
-    result = 31 * result + _hideInactiveBuffers.hashCode()
-    result = 31 * result + _hideInactiveNetworks.hashCode()
-    result = 31 * result + _disableDecoration.hashCode()
-    result = 31 * result + _allowedBufferTypes.hashCode()
-    result = 31 * result + _minimumActivity.hashCode()
-    result = 31 * result + _showSearch.hashCode()
-    return result
-  }
+  fun isEqual(other: BufferViewConfig): Boolean =
+    this.bufferViewName() == other.bufferViewName() ||
+    this.showSearch() == other.showSearch() ||
+    this.sortAlphabetically() == other.sortAlphabetically() ||
+    this.addNewBuffersAutomatically() == other.addNewBuffersAutomatically() ||
+    this.hideInactiveBuffers() == other.hideInactiveBuffers() ||
+    this.hideInactiveNetworks() == other.hideInactiveNetworks() ||
+    this.allowedBufferTypes() == other.allowedBufferTypes() ||
+    this.networkId() == other.networkId() ||
+    this.minimumActivity() == other.minimumActivity()
 
   override fun toString(): String {
     return "BufferViewConfig(_bufferViewId=$_bufferViewId, _bufferViewName='$_bufferViewName', _networkId=$_networkId, _addNewBuffersAutomatically=$_addNewBuffersAutomatically, _sortAlphabetically=$_sortAlphabetically, _hideInactiveBuffers=$_hideInactiveBuffers, _hideInactiveNetworks=$_hideInactiveNetworks, _disableDecoration=$_disableDecoration, _allowedBufferTypes=$_allowedBufferTypes, _minimumActivity=$_minimumActivity, _showSearch=$_showSearch)"
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManager.kt
index 51d512bbc..5cbc1eeb4 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManager.kt
@@ -157,25 +157,10 @@ class HighlightRuleManager(
   private var _highlightNick = IHighlightRuleManager.HighlightNickType.CurrentNick
   private var _nicksCaseSensitive = false
 
-  override fun equals(other: Any?): Boolean {
-    if (this === other) return true
-    if (javaClass != other?.javaClass) return false
-
-    other as HighlightRuleManager
-
-    if (_highlightRuleList != other._highlightRuleList) return false
-    if (_highlightNick != other._highlightNick) return false
-    if (_nicksCaseSensitive != other._nicksCaseSensitive) return false
-
-    return true
-  }
-
-  override fun hashCode(): Int {
-    var result = _highlightRuleList.hashCode()
-    result = 31 * result + _highlightNick.hashCode()
-    result = 31 * result + _nicksCaseSensitive.hashCode()
-    return result
-  }
+  fun isEqual(other: HighlightRuleManager): Boolean =
+    this.highlightNick() == other.highlightNick() ||
+    this.nicksCaseSensitive() == other.nicksCaseSensitive() ||
+    this.highlightRuleList() == other.highlightRuleList()
 
   override fun toString(): String {
     return "HighlightRuleManager(_highlightRuleList=$_highlightRuleList, _highlightNick=$_highlightNick, _nicksCaseSensitive=$_nicksCaseSensitive)"
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt
index 87913c564..0597543de 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt
@@ -309,57 +309,17 @@ class Identity constructor(
       _change.onNext(Unit)
     }
 
-  override fun equals(other: Any?): Boolean {
-    if (this === other) return true
-    if (javaClass != other?.javaClass) return false
-
-    other as Identity
-
-    if (_identityId != other._identityId) return false
-    if (_identityName != other._identityName) return false
-    if (_realName != other._realName) return false
-    if (_nicks != other._nicks) return false
-    if (_awayNick != other._awayNick) return false
-    if (_awayNickEnabled != other._awayNickEnabled) return false
-    if (_awayReason != other._awayReason) return false
-    if (_awayReasonEnabled != other._awayReasonEnabled) return false
-    if (_autoAwayEnabled != other._autoAwayEnabled) return false
-    if (_autoAwayTime != other._autoAwayTime) return false
-    if (_autoAwayReason != other._autoAwayReason) return false
-    if (_autoAwayReasonEnabled != other._autoAwayReasonEnabled) return false
-    if (_detachAwayEnabled != other._detachAwayEnabled) return false
-    if (_detachAwayReason != other._detachAwayReason) return false
-    if (_detachAwayReasonEnabled != other._detachAwayReasonEnabled) return false
-    if (_ident != other._ident) return false
-    if (_kickReason != other._kickReason) return false
-    if (_partReason != other._partReason) return false
-    if (_quitReason != other._quitReason) return false
-
-    return true
-  }
-
-  override fun hashCode(): Int {
-    var result = _identityId
-    result = 31 * result + (_identityName?.hashCode() ?: 0)
-    result = 31 * result + (_realName?.hashCode() ?: 0)
-    result = 31 * result + _nicks.hashCode()
-    result = 31 * result + (_awayNick?.hashCode() ?: 0)
-    result = 31 * result + _awayNickEnabled.hashCode()
-    result = 31 * result + (_awayReason?.hashCode() ?: 0)
-    result = 31 * result + _awayReasonEnabled.hashCode()
-    result = 31 * result + _autoAwayEnabled.hashCode()
-    result = 31 * result + _autoAwayTime
-    result = 31 * result + (_autoAwayReason?.hashCode() ?: 0)
-    result = 31 * result + _autoAwayReasonEnabled.hashCode()
-    result = 31 * result + _detachAwayEnabled.hashCode()
-    result = 31 * result + (_detachAwayReason?.hashCode() ?: 0)
-    result = 31 * result + _detachAwayReasonEnabled.hashCode()
-    result = 31 * result + (_ident?.hashCode() ?: 0)
-    result = 31 * result + (_kickReason?.hashCode() ?: 0)
-    result = 31 * result + (_partReason?.hashCode() ?: 0)
-    result = 31 * result + (_quitReason?.hashCode() ?: 0)
-    return result
-  }
+  fun isEqual(other: Identity): Boolean =
+    this.identityName() == other.identityName() ||
+    this.realName() == other.realName() ||
+    this.ident() == other.ident() ||
+    this.kickReason() == other.kickReason() ||
+    this.partReason() == other.partReason() ||
+    this.quitReason() == other.quitReason() ||
+    this.awayReason() == other.awayReason() ||
+    this.detachAwayEnabled() == other.detachAwayEnabled() ||
+    this.detachAwayReason() == other.detachAwayReason() ||
+    this.nicks() == other.nicks()
 
   override fun toString(): String {
     return "Identity(_identityId=$_identityId, _identityName=$_identityName, _realName=$_realName, _nicks=$_nicks, _awayNick=$_awayNick, _awayNickEnabled=$_awayNickEnabled, _awayReason=$_awayReason, _awayReasonEnabled=$_awayReasonEnabled, _autoAwayEnabled=$_autoAwayEnabled, _autoAwayTime=$_autoAwayTime, _autoAwayReason=$_autoAwayReason, _autoAwayReasonEnabled=$_autoAwayReasonEnabled, _detachAwayEnabled=$_detachAwayEnabled, _detachAwayReason=$_detachAwayReason, _detachAwayReasonEnabled=$_detachAwayReasonEnabled, _ident=$_ident, _kickReason=$_kickReason, _partReason=$_partReason, _quitReason=$_quitReason)"
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
index 06c3663df..abccf0850 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt
@@ -283,20 +283,8 @@ class IgnoreListManager constructor(
       if (initialized) session.backlogManager?.updateIgnoreRules()
     }
 
-  override fun equals(other: Any?): Boolean {
-    if (this === other) return true
-    if (javaClass != other?.javaClass) return false
-
-    other as IgnoreListManager
-
-    if (_ignoreList != other._ignoreList) return false
-
-    return true
-  }
-
-  override fun hashCode(): Int {
-    return _ignoreList.hashCode()
-  }
+  fun isEqual(other: IgnoreListManager): Boolean =
+    this.ignoreList() == other.ignoreList()
 
   override fun toString(): String {
     return "IgnoreListManager(_ignoreList=$_ignoreList)"
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
index 58d19ad07..33ea3b18c 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
@@ -1042,68 +1042,26 @@ class Network constructor(
 
   private val live_networkInfo = BehaviorSubject.createDefault(Unit)
 
-
-  override fun equals(other: Any?): Boolean {
-    if (this === other) return true
-    if (javaClass != other?.javaClass) return false
-
-    other as Network
-
-    if (_networkId != other._networkId) return false
-    if (_identity != other._identity) return false
-    if (_networkName != other._networkName) return false
-    if (_serverList != other._serverList) return false
-    if (_useRandomServer != other._useRandomServer) return false
-    if (_perform != other._perform) return false
-    if (_useAutoIdentify != other._useAutoIdentify) return false
-    if (_autoIdentifyService != other._autoIdentifyService) return false
-    if (_autoIdentifyPassword != other._autoIdentifyPassword) return false
-    if (_useSasl != other._useSasl) return false
-    if (_saslAccount != other._saslAccount) return false
-    if (_saslPassword != other._saslPassword) return false
-    if (_useAutoReconnect != other._useAutoReconnect) return false
-    if (_autoReconnectInterval != other._autoReconnectInterval) return false
-    if (_autoReconnectRetries != other._autoReconnectRetries) return false
-    if (_unlimitedReconnectRetries != other._unlimitedReconnectRetries) return false
-    if (_rejoinChannels != other._rejoinChannels) return false
-    if (_useCustomMessageRate != other._useCustomMessageRate) return false
-    if (_messageRateBurstSize != other._messageRateBurstSize) return false
-    if (_messageRateDelay != other._messageRateDelay) return false
-    if (_unlimitedMessageRate != other._unlimitedMessageRate) return false
-    if (_codecForServer != other._codecForServer) return false
-    if (_codecForEncoding != other._codecForEncoding) return false
-    if (_codecForDecoding != other._codecForDecoding) return false
-
-    return true
-  }
-
-  override fun hashCode(): Int {
-    var result = _networkId
-    result = 31 * result + _identity
-    result = 31 * result + _networkName.hashCode()
-    result = 31 * result + _serverList.hashCode()
-    result = 31 * result + _useRandomServer.hashCode()
-    result = 31 * result + _perform.hashCode()
-    result = 31 * result + _useAutoIdentify.hashCode()
-    result = 31 * result + _autoIdentifyService.hashCode()
-    result = 31 * result + _autoIdentifyPassword.hashCode()
-    result = 31 * result + _useSasl.hashCode()
-    result = 31 * result + _saslAccount.hashCode()
-    result = 31 * result + _saslPassword.hashCode()
-    result = 31 * result + _useAutoReconnect.hashCode()
-    result = 31 * result + _autoReconnectInterval
-    result = 31 * result + _autoReconnectRetries
-    result = 31 * result + _unlimitedReconnectRetries.hashCode()
-    result = 31 * result + _rejoinChannels.hashCode()
-    result = 31 * result + _useCustomMessageRate.hashCode()
-    result = 31 * result + _messageRateBurstSize
-    result = 31 * result + _messageRateDelay
-    result = 31 * result + _unlimitedMessageRate.hashCode()
-    result = 31 * result + _codecForServer.hashCode()
-    result = 31 * result + _codecForEncoding.hashCode()
-    result = 31 * result + _codecForDecoding.hashCode()
-    return result
-  }
+  fun isEqual(other: Network): Boolean =
+    this.networkName() == other.networkName() ||
+    this.identity() == other.identity() ||
+    this.serverList() == other.serverList() ||
+    this.useSasl() == other.useSasl() ||
+    this.saslAccount() == other.saslAccount() ||
+    this.saslPassword() == other.saslPassword() ||
+    this.useAutoIdentify() == other.useAutoIdentify() ||
+    this.autoIdentifyService() == other.autoIdentifyService() ||
+    this.autoIdentifyPassword() == other.autoIdentifyPassword() ||
+    this.useAutoReconnect() == other.useAutoReconnect() ||
+    this.autoReconnectInterval() == other.autoReconnectInterval() ||
+    this.autoReconnectRetries() == other.autoReconnectRetries() ||
+    this.unlimitedReconnectRetries() == other.unlimitedReconnectRetries() ||
+    this.rejoinChannels() == other.rejoinChannels() ||
+    this.perform() == other.perform() ||
+    this.useCustomMessageRate() == other.useCustomMessageRate() ||
+    this.messageRateBurstSize() == other.messageRateBurstSize() ||
+    this.unlimitedMessageRate() == other.unlimitedMessageRate() ||
+    this.messageRateDelay() == other.messageRateDelay()
 
   override fun toString(): String {
     return "Network(_networkId=$_networkId, _identity=$_identity, _networkName='$_networkName', _serverList=$_serverList, _useRandomServer=$_useRandomServer, _perform=$_perform, _useAutoIdentify=$_useAutoIdentify, _autoIdentifyService='$_autoIdentifyService', _autoIdentifyPassword='$_autoIdentifyPassword', _useSasl=$_useSasl, _saslAccount='$_saslAccount', _saslPassword='$_saslPassword', _useAutoReconnect=$_useAutoReconnect, _autoReconnectInterval=$_autoReconnectInterval, _autoReconnectRetries=$_autoReconnectRetries, _unlimitedReconnectRetries=$_unlimitedReconnectRetries, _rejoinChannels=$_rejoinChannels, _useCustomMessageRate=$_useCustomMessageRate, _messageRateBurstSize=$_messageRateBurstSize, _messageRateDelay=$_messageRateDelay, _unlimitedMessageRate=$_unlimitedMessageRate, _codecForServer=$_codecForServer, _codecForEncoding=$_codecForEncoding, _codecForDecoding=$_codecForDecoding)"
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/NetworkConfig.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/NetworkConfig.kt
index 1b731bddf..115105212 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/NetworkConfig.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/NetworkConfig.kt
@@ -127,36 +127,15 @@ class NetworkConfig constructor(
   private var _autoWhoDelay: Int = 5
   private var _standardCtcp: Boolean = false
 
-
-  override fun equals(other: Any?): Boolean {
-    if (this === other) return true
-    if (javaClass != other?.javaClass) return false
-
-    other as NetworkConfig
-
-    if (_pingTimeoutEnabled != other._pingTimeoutEnabled) return false
-    if (_pingInterval != other._pingInterval) return false
-    if (_maxPingCount != other._maxPingCount) return false
-    if (_autoWhoEnabled != other._autoWhoEnabled) return false
-    if (_autoWhoInterval != other._autoWhoInterval) return false
-    if (_autoWhoNickLimit != other._autoWhoNickLimit) return false
-    if (_autoWhoDelay != other._autoWhoDelay) return false
-    if (_standardCtcp != other._standardCtcp) return false
-
-    return true
-  }
-
-  override fun hashCode(): Int {
-    var result = _pingTimeoutEnabled.hashCode()
-    result = 31 * result + _pingInterval
-    result = 31 * result + _maxPingCount
-    result = 31 * result + _autoWhoEnabled.hashCode()
-    result = 31 * result + _autoWhoInterval
-    result = 31 * result + _autoWhoNickLimit
-    result = 31 * result + _autoWhoDelay
-    result = 31 * result + _standardCtcp.hashCode()
-    return result
-  }
+  fun isEqual(other: NetworkConfig): Boolean =
+    this.pingTimeoutEnabled() == other.pingTimeoutEnabled() &&
+    this.pingInterval() == other.pingInterval() &&
+    this.maxPingCount() == other.maxPingCount() &&
+    this.autoWhoEnabled() == other.autoWhoEnabled() &&
+    this.autoWhoInterval() == other.autoWhoInterval() &&
+    this.autoWhoNickLimit() == other.autoWhoNickLimit() &&
+    this.autoWhoDelay() == other.autoWhoDelay() &&
+    this.standardCtcp() == other.standardCtcp()
 
   override fun toString(): String {
     return "NetworkConfig(_pingTimeoutEnabled=$_pingTimeoutEnabled, _pingInterval=$_pingInterval, _maxPingCount=$_maxPingCount, _autoWhoEnabled=$_autoWhoEnabled, _autoWhoInterval=$_autoWhoInterval, _autoWhoNickLimit=$_autoWhoNickLimit, _autoWhoDelay=$_autoWhoDelay, _standardCtcp=$_standardCtcp)"
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/Optional.kt b/lib/src/main/java/de/kuschku/libquassel/util/Optional.kt
index e05fb80d0..dccfd0cdf 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/Optional.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/Optional.kt
@@ -49,7 +49,7 @@ interface Optional<T : Any> : Serializable {
     override fun orNull(): T? = value
     override fun <X : Throwable> orElseThrow(supplier: () -> X) = value
     override fun equals(other: Any?) = (other as? Present<*>)?.value == value
-    override fun hashCode() = value?.hashCode() ?: 0
+    override fun hashCode() = value.hashCode()
     override fun toString() = "Optional[$value]"
   }
 
diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BufferInfoSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BufferInfoSerializerTest.kt
index 2c9964c5c..3c9c312d4 100644
--- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BufferInfoSerializerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/BufferInfoSerializerTest.kt
@@ -25,7 +25,7 @@ package de.kuschku.libquassel.protocol.primitive.serializer
 import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert
+import org.junit.Assert.assertEquals
 import org.junit.Test
 
 class BufferInfoSerializerTest {
@@ -38,7 +38,7 @@ class BufferInfoSerializerTest {
       -1,
       ""
     )
-    Assert.assertEquals(value, roundTrip(BufferInfoSerializer, value))
+    assertEquals(value, roundTrip(BufferInfoSerializer, value))
   }
 
   @Test
@@ -50,6 +50,6 @@ class BufferInfoSerializerTest {
       Int.MAX_VALUE,
       "äẞ\u0000\uFFFF"
     )
-    Assert.assertEquals(value, roundTrip(BufferInfoSerializer, value))
+    assertEquals(value, roundTrip(BufferInfoSerializer, value))
   }
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/AliasManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/AliasManagerTest.kt
index 3d5835925..ca565e904 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/AliasManagerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/AliasManagerTest.kt
@@ -25,7 +25,6 @@ package de.kuschku.libquassel.quassel.syncables
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert
 import org.junit.Test
 
 class AliasManagerTest {
@@ -36,7 +35,7 @@ class AliasManagerTest {
 
     val copy = original.copy()
     copy.fromVariantMap(roundTrip(VariantMapSerializer, original.toVariantMap()))
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 
   @Test
@@ -46,6 +45,6 @@ class AliasManagerTest {
 
     val copy = original.copy()
     copy.fromVariantMap(original.toVariantMap())
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfigTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfigTest.kt
index 16f04f08a..dabda1aea 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfigTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfigTest.kt
@@ -27,7 +27,6 @@ import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.*
-import org.junit.Assert
 import org.junit.Test
 
 class BufferViewConfigTest {
@@ -47,7 +46,7 @@ class BufferViewConfigTest {
 
     val copy = original.copy()
     copy.fromVariantMap(roundTrip(VariantMapSerializer, original.toVariantMap()))
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 
   @Test
@@ -66,6 +65,6 @@ class BufferViewConfigTest {
 
     val copy = original.copy()
     copy.fromVariantMap(original.toVariantMap())
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManagerTest.kt
index f57f4c730..d54d20c8b 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManagerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/HighlightRuleManagerTest.kt
@@ -29,7 +29,6 @@ import de.kuschku.libquassel.util.randomBoolean
 import de.kuschku.libquassel.util.randomOf
 import de.kuschku.libquassel.util.randomString
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert
 import org.junit.Test
 
 class HighlightRuleManagerTest {
@@ -70,7 +69,7 @@ class HighlightRuleManagerTest {
 
     val copy = original.copy()
     copy.fromVariantMap(roundTrip(VariantMapSerializer, original.toVariantMap()))
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 
   @Test
@@ -110,6 +109,6 @@ class HighlightRuleManagerTest {
 
     val copy = original.copy()
     copy.fromVariantMap(original.toVariantMap())
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IdentityTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IdentityTest.kt
index 9a2ae45d4..bc86422b7 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IdentityTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IdentityTest.kt
@@ -27,7 +27,6 @@ import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.randomString
 import de.kuschku.libquassel.util.randomUInt
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert
 import org.junit.Test
 
 class IdentityTest {
@@ -45,7 +44,7 @@ class IdentityTest {
 
     val copy = original.copy()
     copy.fromVariantMap(roundTrip(VariantMapSerializer, original.toVariantMap()))
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 
   @Test
@@ -62,6 +61,6 @@ class IdentityTest {
 
     val copy = original.copy()
     copy.fromVariantMap(original.toVariantMap())
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt
index 0de147d50..54e41b802 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt
@@ -29,7 +29,6 @@ import de.kuschku.libquassel.util.randomBoolean
 import de.kuschku.libquassel.util.randomOf
 import de.kuschku.libquassel.util.randomString
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert
 import org.junit.Test
 
 class IgnoreListManagerTest {
@@ -61,7 +60,7 @@ class IgnoreListManagerTest {
 
     val copy = original.copy()
     copy.fromVariantMap(roundTrip(VariantMapSerializer, original.toVariantMap()))
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 
   @Test
@@ -92,6 +91,6 @@ class IgnoreListManagerTest {
 
     val copy = original.copy()
     copy.fromVariantMap(original.toVariantMap())
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkConfigTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkConfigTest.kt
index c14e4acaa..a2eae497b 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkConfigTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkConfigTest.kt
@@ -27,7 +27,6 @@ import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.randomBoolean
 import de.kuschku.libquassel.util.randomUInt
 import de.kuschku.libquassel.util.roundTrip
-import org.junit.Assert
 import org.junit.Test
 
 class NetworkConfigTest {
@@ -45,7 +44,7 @@ class NetworkConfigTest {
 
     val copy = original.copy()
     copy.fromVariantMap(roundTrip(VariantMapSerializer, original.toVariantMap()))
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 
   @Test
@@ -62,6 +61,6 @@ class NetworkConfigTest {
 
     val copy = original.copy()
     copy.fromVariantMap(original.toVariantMap())
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 }
diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkTest.kt
index 16f20d27d..7c4ba0538 100644
--- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkTest.kt
+++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/NetworkTest.kt
@@ -26,7 +26,6 @@ import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.*
-import org.junit.Assert
 import org.junit.Test
 
 class NetworkTest {
@@ -78,7 +77,7 @@ class NetworkTest {
 
     val copy = original.copy()
     copy.fromVariantMap(roundTrip(VariantMapSerializer, original.toVariantMap()))
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 
   @Test
@@ -130,6 +129,6 @@ class NetworkTest {
 
     val copy = original.copy()
     copy.fromVariantMap(original.toVariantMap())
-    Assert.assertEquals(original, copy)
+    assert(original.isEqual(copy))
   }
 }
diff --git a/slidingpanel/src/main/java/com/sothree/slidinguppanel/SlidingUpPanelLayout.java b/slidingpanel/src/main/java/com/sothree/slidinguppanel/SlidingUpPanelLayout.java
index 5e6937080..e8d904a9a 100644
--- a/slidingpanel/src/main/java/com/sothree/slidinguppanel/SlidingUpPanelLayout.java
+++ b/slidingpanel/src/main/java/com/sothree/slidinguppanel/SlidingUpPanelLayout.java
@@ -1,3 +1,25 @@
+/*
+ * QuasselDroid - Quassel client for Android
+ *
+ * Copyright (c) 2018 Janne Koschinski
+ * Copyright (c) 2018 Ken Børge Viktil
+ * Copyright (c) 2018 Magnus Fjell
+ * Copyright (c) 2018 Martin Sandsmark
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 package com.sothree.slidinguppanel;
 
 import android.annotation.SuppressLint;
@@ -434,8 +456,6 @@ public class SlidingUpPanelLayout extends ViewGroup {
 
   /**
    * Adds a panel slide listener
-   *
-   * @param listener
    */
   public void addPanelSlideListener(PanelSlideListener listener) {
     synchronized (mPanelSlideListeners) {
@@ -445,8 +465,6 @@ public class SlidingUpPanelLayout extends ViewGroup {
 
   /**
    * Removes a panel slide listener
-   *
-   * @param listener
    */
   public void removePanelSlideListener(PanelSlideListener listener) {
     synchronized (mPanelSlideListeners) {
@@ -458,8 +476,6 @@ public class SlidingUpPanelLayout extends ViewGroup {
    * Provides an on click for the portion of the main view that is dimmed. The listener is not
    * triggered if the panel is in a collapsed or a hidden position. If the on click listener is
    * not provided, the clicks on the dimmed area are passed through to the main layout.
-   *
-   * @param listener
    */
   public void setFadeOnClickListener(View.OnClickListener listener) {
     mFadeOnClickListener = listener;
@@ -538,8 +554,6 @@ public class SlidingUpPanelLayout extends ViewGroup {
 
   /**
    * Sets the current scrollable view helper. See ScrollableViewHelper description for details.
-   *
-   * @param helper
    */
   public void setScrollableViewHelper(ScrollableViewHelper helper) {
     mScrollableViewHelper = helper;
@@ -577,8 +591,6 @@ public class SlidingUpPanelLayout extends ViewGroup {
 
   /**
    * Sets whether or not the panel overlays the content
-   *
-   * @param overlayed
    */
   public void setOverlayed(boolean overlayed) {
     mOverlayContent = overlayed;
@@ -593,8 +605,6 @@ public class SlidingUpPanelLayout extends ViewGroup {
 
   /**
    * Sets whether or not the main content is clipped to the top of the panel
-   *
-   * @param clip
    */
   public void setClipPanel(boolean clip) {
     mClipPanel = clip;
@@ -922,78 +932,82 @@ public class SlidingUpPanelLayout extends ViewGroup {
     final float x = ev.getX();
     final float y = ev.getY();
 
-    if (action == MotionEvent.ACTION_DOWN) {
-      mIsScrollableViewHandlingTouch = false;
-      mPrevMotionX = x;
-      mPrevMotionY = y;
-    } else if (action == MotionEvent.ACTION_MOVE) {
-      float dx = x - mPrevMotionX;
-      float dy = y - mPrevMotionY;
-      mPrevMotionX = x;
-      mPrevMotionY = y;
-
-      if (Math.abs(dx) > Math.abs(dy)) {
-        // Scrolling horizontally, so ignore
-        return super.dispatchTouchEvent(ev);
-      }
-
-      // If the scroll view isn't under the touch, pass the
-      // event along to the dragView.
-      if (!checkTouchingDragView(mScrollableView, (int) mInitialMotionX, (int) mInitialMotionY)) {
-        return super.dispatchTouchEvent(ev);
-      }
-
-      // Which direction (up or down) is the drag moving?
-      if (dy * (mIsSlidingUp ? 1 : -1) > 0) { // Collapsing
-        // Is the child less than fully scrolled?
-        // Then let the child handle it.
-        if (mScrollableViewHelper.getScrollableViewScrollPosition(mScrollableView, mIsSlidingUp) > 0) {
-          mIsScrollableViewHandlingTouch = true;
+    switch (action) {
+      case MotionEvent.ACTION_DOWN:
+        mIsScrollableViewHandlingTouch = false;
+        mPrevMotionX = x;
+        mPrevMotionY = y;
+        break;
+      case MotionEvent.ACTION_MOVE:
+        float dx = x - mPrevMotionX;
+        float dy = y - mPrevMotionY;
+        mPrevMotionX = x;
+        mPrevMotionY = y;
+
+        if (Math.abs(dx) > Math.abs(dy)) {
+          // Scrolling horizontally, so ignore
           return super.dispatchTouchEvent(ev);
         }
 
-        // Was the child handling the touch previously?
-        // Then we need to rejigger things so that the
-        // drag panel gets a proper down event.
-        if (mIsScrollableViewHandlingTouch) {
-          // Send an 'UP' event to the child.
-          MotionEvent up = MotionEvent.obtain(ev);
-          up.setAction(MotionEvent.ACTION_CANCEL);
-          super.dispatchTouchEvent(up);
-          up.recycle();
-
-          // Send a 'DOWN' event to the panel. (We'll cheat
-          // and hijack this one)
-          ev.setAction(MotionEvent.ACTION_DOWN);
+        // If the scroll view isn't under the touch, pass the
+        // event along to the dragView.
+        if (!checkTouchingDragView(mScrollableView, (int) mInitialMotionX, (int) mInitialMotionY)) {
+          return super.dispatchTouchEvent(ev);
         }
 
-        mIsScrollableViewHandlingTouch = false;
-        return this.onTouchEvent(ev);
-      } else if (dy * (mIsSlidingUp ? 1 : -1) < 0) { // Expanding
-        // Is the panel less than fully expanded?
-        // Then we'll handle the drag here.
-        if (mSlideOffset < 1.0f) {
+        // Which direction (up or down) is the drag moving?
+        if (dy * (mIsSlidingUp ? 1 : -1) > 0) { // Collapsing
+          // Is the child less than fully scrolled?
+          // Then let the child handle it.
+          if (mScrollableViewHelper.getScrollableViewScrollPosition(mScrollableView, mIsSlidingUp) > 0) {
+            mIsScrollableViewHandlingTouch = true;
+            return super.dispatchTouchEvent(ev);
+          }
+
+          // Was the child handling the touch previously?
+          // Then we need to rejigger things so that the
+          // drag panel gets a proper down event.
+          if (mIsScrollableViewHandlingTouch) {
+            // Send an 'UP' event to the child.
+            MotionEvent up = MotionEvent.obtain(ev);
+            up.setAction(MotionEvent.ACTION_CANCEL);
+            super.dispatchTouchEvent(up);
+            up.recycle();
+
+            // Send a 'DOWN' event to the panel. (We'll cheat
+            // and hijack this one)
+            ev.setAction(MotionEvent.ACTION_DOWN);
+          }
+
           mIsScrollableViewHandlingTouch = false;
           return this.onTouchEvent(ev);
-        }
+        } else if (dy * (mIsSlidingUp ? 1 : -1) < 0) { // Expanding
+          // Is the panel less than fully expanded?
+          // Then we'll handle the drag here.
+          if (mSlideOffset < 1.0f) {
+            mIsScrollableViewHandlingTouch = false;
+            return this.onTouchEvent(ev);
+          }
 
-        // Was the panel handling the touch previously?
-        // Then we need to rejigger things so that the
-        // child gets a proper down event.
-        if (!mIsScrollableViewHandlingTouch && mDragHelper.isDragging()) {
-          mDragHelper.cancel();
-          ev.setAction(MotionEvent.ACTION_DOWN);
-        }
+          // Was the panel handling the touch previously?
+          // Then we need to rejigger things so that the
+          // child gets a proper down event.
+          if (!mIsScrollableViewHandlingTouch && mDragHelper.isDragging()) {
+            mDragHelper.cancel();
+            ev.setAction(MotionEvent.ACTION_DOWN);
+          }
 
-        mIsScrollableViewHandlingTouch = true;
-        return super.dispatchTouchEvent(ev);
-      }
-    } else if (action == MotionEvent.ACTION_UP) {
-      // If the scrollable view was handling the touch and we receive an up
-      // we want to clear any previous dragging state so we don't intercept a touch stream accidentally
-      if (mIsScrollableViewHandlingTouch) {
-        mDragHelper.setDragState(ViewDragHelper.STATE_IDLE);
-      }
+          mIsScrollableViewHandlingTouch = true;
+          return super.dispatchTouchEvent(ev);
+        }
+        break;
+      case MotionEvent.ACTION_UP:
+        // If the scrollable view was handling the touch and we receive an up
+        // we want to clear any previous dragging state so we don't intercept a touch stream accidentally
+        if (mIsScrollableViewHandlingTouch) {
+          mDragHelper.setDragState(ViewDragHelper.STATE_IDLE);
+        }
+        break;
     }
 
     // In all other cases, just let the default behavior take over.
@@ -1441,7 +1455,7 @@ public class SlidingUpPanelLayout extends ViewGroup {
 
     @Override
     public void onViewReleased(View releasedChild, float xvel, float yvel) {
-      int target = 0;
+      int target;
 
       // direction is always positive if we are sliding in the expanded direction
       float direction = mIsSlidingUp ? -yvel : yvel;
-- 
GitLab