From 59b32b7b844b25abb848e48643757e63902c736e Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Tue, 13 Sep 2016 21:41:39 +0200
Subject: [PATCH] Fixed several bugs

---
 .../libquassel/client/IdentityManager.java    |   6 +-
 .../libquassel/client/NetworkManager.java     |   6 +-
 .../libquassel/localtypes/BacklogFilter.java  |   8 +-
 .../backlogstorage/BacklogStorage.java        |   6 +-
 .../backlogstorage/HybridBacklogStorage.java  |  14 +-
 .../syncables/types/impl/AliasManager.java    |   8 +-
 .../syncables/types/impl/BacklogManager.java  |   6 +-
 .../syncables/types/impl/BufferSyncer.java    |   8 +-
 .../types/impl/BufferViewManager.java         |   6 +-
 .../types/impl/IgnoreListManager.java         |   6 +-
 .../types/interfaces/QAliasManager.java       |   6 +-
 .../types/interfaces/QBacklogManager.java     |   6 +-
 .../types/interfaces/QBufferViewManager.java  |   4 +-
 .../types/interfaces/QIgnoreListManager.java  |   4 +-
 .../ui/chat/chatview/MessageAdapter.java      |   4 +-
 .../chat/drawer/BufferViewConfigAdapter.java  |   8 +-
 .../ui/chat/drawer/NetworkItem.java           |  37 +-
 .../ui/chat/fragment/ChatFragment.java        |   4 +-
 .../ui/chat/nicklist/NickListAdapter.java     |  29 +-
 .../identity/IdentitySpinnerAdapter.java      |   4 +-
 .../network/FakeNetworksWrapper.java          |   6 +-
 ...AndroidObservableComparableSortedList.java |  58 +++
 .../lists/AndroidObservableSortedList.java    | 372 ++++++++++++++++++
 ...ildParentAndroidObservableSortedList.java} |   6 +-
 .../lists/ObservableComparableSortedList.java |  34 +-
 .../lists/ObservableSortedList.java           | 346 +++++-----------
 .../main/res/layout/activity_alias_edit.xml   |   4 +-
 .../res/layout/activity_channel_detail.xml    |   4 +-
 .../res/layout/activity_chatlist_edit.xml     |   3 +-
 .../res/layout/activity_chatlist_list.xml     |   3 +-
 .../res/layout/activity_identity_edit.xml     |   4 +-
 .../res/layout/activity_ignorerule_edit.xml   |   3 +-
 .../main/res/layout/activity_network_edit.xml |   3 +-
 .../main/res/layout/activity_network_list.xml |   3 +-
 .../layout/activity_networkserver_edit.xml    |   3 +-
 app/src/main/res/layout/activity_settings.xml |  12 +-
 app/src/main/res/layout/widget_actionbar.xml  |   1 +
 37 files changed, 644 insertions(+), 401 deletions(-)
 create mode 100644 app/src/main/java/de/kuschku/util/observables/lists/AndroidObservableComparableSortedList.java
 create mode 100644 app/src/main/java/de/kuschku/util/observables/lists/AndroidObservableSortedList.java
 rename app/src/main/java/de/kuschku/util/observables/lists/{ChildParentObservableSortedList.java => ChildParentAndroidObservableSortedList.java} (87%)

diff --git a/app/src/main/java/de/kuschku/libquassel/client/IdentityManager.java b/app/src/main/java/de/kuschku/libquassel/client/IdentityManager.java
index 8d7ab9483..feff60900 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/IdentityManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/IdentityManager.java
@@ -30,12 +30,12 @@ import java.util.List;
 import java.util.Map;
 
 import de.kuschku.libquassel.syncables.types.interfaces.QIdentity;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 public class IdentityManager {
     @NonNull
     private final Map<Integer, QIdentity> identities = new HashMap<>();
-    private final ObservableSortedList<QIdentity> identityList = new ObservableSortedList<>(QIdentity.class, new ObservableSortedList.ItemComparator<QIdentity>() {
+    private final AndroidObservableSortedList<QIdentity> identityList = new AndroidObservableSortedList<>(QIdentity.class, new AndroidObservableSortedList.ItemComparator<QIdentity>() {
         @Override
         public int compare(QIdentity o1, QIdentity o2) {
             if (o1 == null && o2 == null)
@@ -78,7 +78,7 @@ public class IdentityManager {
         }
     }
 
-    public ObservableSortedList<QIdentity> identities() {
+    public AndroidObservableSortedList<QIdentity> identities() {
         return identityList;
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/client/NetworkManager.java b/app/src/main/java/de/kuschku/libquassel/client/NetworkManager.java
index 4a2343884..7bc59075f 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/NetworkManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/NetworkManager.java
@@ -33,7 +33,7 @@ import de.kuschku.libquassel.events.ConnectionChangeEvent;
 import de.kuschku.libquassel.syncables.types.impl.Network;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
@@ -41,7 +41,7 @@ public class NetworkManager extends Observable {
     @NonNull
     private final Map<Integer, QNetwork> networks = new HashMap<>();
     @NonNull
-    private final ObservableSortedList<QNetwork> list = new ObservableSortedList<QNetwork>(QNetwork.class, new ObservableSortedList.ItemComparator<QNetwork>() {
+    private final AndroidObservableSortedList<QNetwork> list = new AndroidObservableSortedList<QNetwork>(QNetwork.class, new AndroidObservableSortedList.ItemComparator<QNetwork>() {
         @Override
         public int compare(QNetwork o1, QNetwork o2) {
             assertNotNull(o1);
@@ -132,7 +132,7 @@ public class NetworkManager extends Observable {
     }
 
     @NonNull
-    public ObservableSortedList<QNetwork> networks() {
+    public AndroidObservableSortedList<QNetwork> networks() {
         return list;
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java b/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java
index c671d95cf..af6edeae3 100644
--- a/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java
+++ b/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java
@@ -38,7 +38,7 @@ import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.util.observables.callbacks.ElementCallback;
 import de.kuschku.util.observables.callbacks.UICallback;
-import de.kuschku.util.observables.lists.ObservableComparableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableComparableSortedList;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
@@ -47,9 +47,9 @@ public class BacklogFilter implements UICallback {
     private final Client client;
     private final int bufferId;
     @NonNull
-    private final ObservableComparableSortedList<Message> unfiltered;
+    private final AndroidObservableComparableSortedList<Message> unfiltered;
     @NonNull
-    private final ObservableComparableSortedList<Message> filtered;
+    private final AndroidObservableComparableSortedList<Message> filtered;
 
     private final EventBus bus = new EventBus();
     ElementCallback<Message.Type> typeCallback = new ElementCallback<Message.Type>() {
@@ -72,7 +72,7 @@ public class BacklogFilter implements UICallback {
     private CharSequence searchQuery;
     private Message markerlineMessage;
 
-    public BacklogFilter(@NonNull Client client, int bufferId, @NonNull ObservableComparableSortedList<Message> unfiltered, @NonNull ObservableComparableSortedList<Message> filtered) {
+    public BacklogFilter(@NonNull Client client, int bufferId, @NonNull AndroidObservableComparableSortedList<Message> unfiltered, @NonNull AndroidObservableComparableSortedList<Message> filtered) {
         this.client = client;
         this.bufferId = bufferId;
         this.unfiltered = unfiltered;
diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java
index ba833ae85..953dbebca 100644
--- a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java
+++ b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/BacklogStorage.java
@@ -30,14 +30,14 @@ import java.util.Set;
 import de.kuschku.libquassel.client.Client;
 import de.kuschku.libquassel.localtypes.BacklogFilter;
 import de.kuschku.libquassel.message.Message;
-import de.kuschku.util.observables.lists.ObservableComparableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableComparableSortedList;
 
 public interface BacklogStorage {
     @NonNull
-    ObservableComparableSortedList<Message> getUnfiltered(@IntRange(from = 0) int bufferid);
+    AndroidObservableComparableSortedList<Message> getUnfiltered(@IntRange(from = 0) int bufferid);
 
     @NonNull
-    ObservableComparableSortedList<Message> getFiltered(@IntRange(from = 0) int bufferid);
+    AndroidObservableComparableSortedList<Message> getFiltered(@IntRange(from = 0) int bufferid);
 
     @NonNull
     BacklogFilter getFilter(@IntRange(from = 0) int bufferid);
diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java
index c527571e4..a902a2068 100644
--- a/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java
+++ b/app/src/main/java/de/kuschku/libquassel/localtypes/backlogstorage/HybridBacklogStorage.java
@@ -39,15 +39,15 @@ import de.kuschku.libquassel.localtypes.BacklogFilter;
 import de.kuschku.libquassel.localtypes.orm.ConnectedDatabase;
 import de.kuschku.libquassel.message.Message;
 import de.kuschku.libquassel.message.Message_Table;
-import de.kuschku.util.observables.lists.ObservableComparableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableComparableSortedList;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
 public class HybridBacklogStorage implements BacklogStorage {
     @NonNull
-    private final SparseArray<ObservableComparableSortedList<Message>> backlogs = new SparseArray<>();
+    private final SparseArray<AndroidObservableComparableSortedList<Message>> backlogs = new SparseArray<>();
     @NonNull
-    private final SparseArray<ObservableComparableSortedList<Message>> filteredBacklogs = new SparseArray<>();
+    private final SparseArray<AndroidObservableComparableSortedList<Message>> filteredBacklogs = new SparseArray<>();
     @NonNull
     private final SparseArray<BacklogFilter> filters = new SparseArray<>();
     @NonNull
@@ -59,14 +59,14 @@ public class HybridBacklogStorage implements BacklogStorage {
 
     @NonNull
     @Override
-    public ObservableComparableSortedList<Message> getUnfiltered(@IntRange(from = -1) int bufferid) {
+    public AndroidObservableComparableSortedList<Message> getUnfiltered(@IntRange(from = -1) int bufferid) {
         ensureExisting(bufferid);
         return backlogs.get(bufferid);
     }
 
     @NonNull
     @Override
-    public ObservableComparableSortedList<Message> getFiltered(@IntRange(from = -1) int bufferid) {
+    public AndroidObservableComparableSortedList<Message> getFiltered(@IntRange(from = -1) int bufferid) {
         ensureExisting(bufferid);
         return filteredBacklogs.get(bufferid);
     }
@@ -222,8 +222,8 @@ public class HybridBacklogStorage implements BacklogStorage {
     private void ensureExisting(@IntRange(from = -1) int bufferId) {
         assertNotNull(client);
         if (backlogs.get(bufferId) == null) {
-            ObservableComparableSortedList<Message> messages = new ObservableComparableSortedList<>(Message.class, true);
-            ObservableComparableSortedList<Message> filteredMessages = new ObservableComparableSortedList<>(Message.class, true);
+            AndroidObservableComparableSortedList<Message> messages = new AndroidObservableComparableSortedList<>(Message.class, true);
+            AndroidObservableComparableSortedList<Message> filteredMessages = new AndroidObservableComparableSortedList<>(Message.class, true);
             BacklogFilter backlogFilter = new BacklogFilter(client, bufferId, messages, filteredMessages);
             if (client.bufferSyncer() != null) {
                 backlogFilter.setMarkerlineMessage(client.bufferSyncer().markerLine(bufferId));
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/AliasManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/AliasManager.java
index 72c1b7997..e5a4443ed 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/AliasManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/AliasManager.java
@@ -46,7 +46,7 @@ import de.kuschku.libquassel.syncables.types.interfaces.QAliasManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.util.backports.Objects;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 public class AliasManager extends AAliasManager {
     @NonNull
@@ -63,7 +63,7 @@ public class AliasManager extends AAliasManager {
     };
 
     private Map<String, Alias> map = new HashMap<>();
-    private ObservableSortedList<Alias> aliases = new ObservableSortedList<>(Alias.class, new ObservableSortedList.ItemComparator<Alias>() {
+    private AndroidObservableSortedList<Alias> aliases = new AndroidObservableSortedList<>(Alias.class, new AndroidObservableSortedList.ItemComparator<Alias>() {
         @Override
         public int compare(Alias o1, Alias o2) {
             return o1.name.compareTo(o2.name);
@@ -163,12 +163,12 @@ public class AliasManager extends AAliasManager {
     }
 
     @Override
-    public ObservableSortedList<Alias> aliases() {
+    public AndroidObservableSortedList<Alias> aliases() {
         return aliases;
     }
 
     @Override
-    public ObservableSortedList<Alias> defaults() {
+    public AndroidObservableSortedList<Alias> defaults() {
         map.clear();
         aliases.clear();
         for (Alias alias : DEFAULTS) {
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BacklogManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BacklogManager.java
index f5748dfaa..c8b713ae3 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BacklogManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BacklogManager.java
@@ -44,7 +44,7 @@ import de.kuschku.libquassel.message.Message_Table;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.types.abstracts.ABacklogManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager;
-import de.kuschku.util.observables.lists.ObservableComparableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableComparableSortedList;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
@@ -157,13 +157,13 @@ public class BacklogManager extends ABacklogManager {
 
     @NonNull
     @Override
-    public ObservableComparableSortedList<Message> unfiltered(int id) {
+    public AndroidObservableComparableSortedList<Message> unfiltered(int id) {
         return storage.getUnfiltered(id);
     }
 
     @NonNull
     @Override
-    public ObservableComparableSortedList<Message> filtered(int id) {
+    public AndroidObservableComparableSortedList<Message> filtered(int id) {
         return storage.getFiltered(id);
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java
index cba73fa3d..5ec3da31c 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java
@@ -37,10 +37,10 @@ import de.kuschku.libquassel.syncables.types.abstracts.ABufferSyncer;
 import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferSyncer;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
-import de.kuschku.util.observables.lists.ObservableComparableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableComparableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 import de.kuschku.util.observables.lists.ObservableElement;
 import de.kuschku.util.observables.lists.ObservableSet;
-import de.kuschku.util.observables.lists.ObservableSortedList;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
@@ -91,7 +91,7 @@ public class BufferSyncer extends ABufferSyncer {
             lastSeenMsgs.put(buffer, msgId);
         }
         setActivity(buffer, 0);
-        ObservableComparableSortedList<Message> filtered = backlogManager.filtered(buffer);
+        AndroidObservableComparableSortedList<Message> filtered = backlogManager.filtered(buffer);
         for (Message m : filtered) {
             addActivity(m);
         }
@@ -185,7 +185,7 @@ public class BufferSyncer extends ABufferSyncer {
     public void _markBufferAsRead(int buffer) {
         assertNotNull(client);
 
-        ObservableSortedList<Message> messages = client.backlogStorage().getUnfiltered(buffer);
+        AndroidObservableSortedList<Message> messages = client.backlogStorage().getUnfiltered(buffer);
         Message lastMessage = messages.last();
         if (messages.isEmpty() || lastMessage == null) {
             _setLastSeenMsg(buffer, -1);
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewManager.java
index 28d536f3d..5cf8fe429 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewManager.java
@@ -36,13 +36,13 @@ import de.kuschku.libquassel.syncables.types.abstracts.ABufferViewManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
 import de.kuschku.util.observables.callbacks.GeneralCallback;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 public class BufferViewManager extends ABufferViewManager {
     @NonNull
     final
     Set<Integer> cachedIds = new HashSet<>();
-    final ObservableSortedList<QBufferViewConfig> list = new ObservableSortedList<>(QBufferViewConfig.class, new ObservableSortedList.ItemComparator<QBufferViewConfig>() {
+    final AndroidObservableSortedList<QBufferViewConfig> list = new AndroidObservableSortedList<>(QBufferViewConfig.class, new AndroidObservableSortedList.ItemComparator<QBufferViewConfig>() {
         @Override
         public int compare(QBufferViewConfig o1, QBufferViewConfig o2) {
             return o1.bufferViewName().compareToIgnoreCase(o2.bufferViewName());
@@ -67,7 +67,7 @@ public class BufferViewManager extends ABufferViewManager {
 
     @NonNull
     @Override
-    public ObservableSortedList<QBufferViewConfig> bufferViewConfigs() {
+    public AndroidObservableSortedList<QBufferViewConfig> bufferViewConfigs() {
         return list;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IgnoreListManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IgnoreListManager.java
index 9414a84d6..fe1274855 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IgnoreListManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IgnoreListManager.java
@@ -37,14 +37,14 @@ import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.serializers.IgnoreListManagerSerializer;
 import de.kuschku.libquassel.syncables.types.abstracts.AIgnoreListManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 import de.kuschku.util.regex.SmartRegEx;
 
 import static de.kuschku.util.AndroidAssert.assertEquals;
 
 public class IgnoreListManager extends AIgnoreListManager {
     @NonNull
-    private final ObservableSortedList<IgnoreListItem> ignoreList = new ObservableSortedList<>(IgnoreListItem.class, new ObservableSortedList.ItemComparator<IgnoreListItem>() {
+    private final AndroidObservableSortedList<IgnoreListItem> ignoreList = new AndroidObservableSortedList<>(IgnoreListItem.class, new AndroidObservableSortedList.ItemComparator<IgnoreListItem>() {
         @Override
         public int compare(IgnoreListItem o1, IgnoreListItem o2) {
             return o1.ignoreRule.rule().compareTo(o2.ignoreRule.rule());
@@ -184,7 +184,7 @@ public class IgnoreListManager extends AIgnoreListManager {
     }
 
     @Override
-    public ObservableSortedList<? extends IgnoreListItem> ignoreList() {
+    public AndroidObservableSortedList<? extends IgnoreListItem> ignoreList() {
         return ignoreList;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QAliasManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QAliasManager.java
index 89dce5455..08588cf85 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QAliasManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QAliasManager.java
@@ -30,7 +30,7 @@ import de.kuschku.libquassel.objects.types.Command;
 import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.Synced;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 public interface QAliasManager extends QObservable<QAliasManager> {
     boolean contains(final String name);
@@ -39,9 +39,9 @@ public interface QAliasManager extends QObservable<QAliasManager> {
 
     int count();
 
-    ObservableSortedList<Alias> aliases();
+    AndroidObservableSortedList<Alias> aliases();
 
-    ObservableSortedList<Alias> defaults();
+    AndroidObservableSortedList<Alias> defaults();
 
     // TODO: specify later on
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBacklogManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBacklogManager.java
index 783938276..3e7bc60e7 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBacklogManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBacklogManager.java
@@ -29,7 +29,7 @@ import java.util.Set;
 import de.kuschku.libquassel.localtypes.BacklogFilter;
 import de.kuschku.libquassel.message.Message;
 import de.kuschku.libquassel.syncables.Synced;
-import de.kuschku.util.observables.lists.ObservableComparableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableComparableSortedList;
 
 public interface QBacklogManager extends QSyncableObject<QBacklogManager> {
     void requestMoreBacklog(int bufferId, int amount);
@@ -60,10 +60,10 @@ public interface QBacklogManager extends QSyncableObject<QBacklogManager> {
     BacklogFilter filter(int id);
 
     @NonNull
-    ObservableComparableSortedList<Message> unfiltered(int id);
+    AndroidObservableComparableSortedList<Message> unfiltered(int id);
 
     @NonNull
-    ObservableComparableSortedList<Message> filtered(int id);
+    AndroidObservableComparableSortedList<Message> filtered(int id);
 
     void setOpen(int bufferId);
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewManager.java
index 227c8efb8..b229c1409 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewManager.java
@@ -27,11 +27,11 @@ import java.util.List;
 import java.util.Map;
 
 import de.kuschku.libquassel.syncables.Synced;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 public interface QBufferViewManager extends QSyncableObject<QBufferViewManager> {
     @NonNull
-    ObservableSortedList<QBufferViewConfig> bufferViewConfigs();
+    AndroidObservableSortedList<QBufferViewConfig> bufferViewConfigs();
 
     QBufferViewConfig bufferViewConfig(int bufferViewId);
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIgnoreListManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIgnoreListManager.java
index 302cac782..e088534fc 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIgnoreListManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIgnoreListManager.java
@@ -29,7 +29,7 @@ import de.kuschku.libquassel.message.Message;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.Synced;
 import de.kuschku.libquassel.syncables.types.impl.IgnoreListManager;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 public interface QIgnoreListManager extends QObservable<QIgnoreListManager> {
     @Synced
@@ -64,7 +64,7 @@ public interface QIgnoreListManager extends QObservable<QIgnoreListManager> {
 
     void requestUpdate();
 
-    ObservableSortedList<? extends IgnoreListManager.IgnoreListItem> ignoreList();
+    AndroidObservableSortedList<? extends IgnoreListManager.IgnoreListItem> ignoreList();
 
     void _toggleIgnoreRule(IgnoreListManager.IgnoreListItem ignoreRule, boolean active);
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/MessageAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/MessageAdapter.java
index af4909d0f..f058cc4f3 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/MessageAdapter.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/MessageAdapter.java
@@ -34,8 +34,8 @@ import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
 import de.kuschku.util.observables.AutoScroller;
 import de.kuschku.util.observables.callbacks.UICallback;
 import de.kuschku.util.observables.callbacks.wrappers.AdapterUICallbackWrapper;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 import de.kuschku.util.observables.lists.IObservableList;
-import de.kuschku.util.observables.lists.ObservableSortedList;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
@@ -59,7 +59,7 @@ public class MessageAdapter extends RecyclerView.Adapter<MessageViewHolder> {
         this.callback = new AdapterUICallbackWrapper(this, scroller);
     }
 
-    public void setMessageList(@Nullable ObservableSortedList<Message> messageList) {
+    public void setMessageList(@Nullable AndroidObservableSortedList<Message> messageList) {
         if (this.messageList != null)
             this.messageList.removeCallback(callback);
         this.messageList = messageList;
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java
index 446faf819..a3a008e0f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java
@@ -41,14 +41,14 @@ import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
 import de.kuschku.util.observables.callbacks.ElementCallback;
 import de.kuschku.util.observables.callbacks.UICallback;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 import de.kuschku.util.observables.lists.ObservableElement;
-import de.kuschku.util.observables.lists.ObservableSortedList;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
 public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkViewHolder, BufferViewHolder> implements OnBufferClickListener, OnBufferLongClickListener {
     private final AppContext context;
-    private final ObservableSortedList<NetworkItem> items;
+    private final AndroidObservableSortedList<NetworkItem> items;
     private final Map<QNetwork, NetworkItem> itemMap = new WeakHashMap<>();
     private final Map<Integer, BufferViewHolder> bufferViewHolderMap = new WeakHashMap<>();
     private final ObservableElement<Boolean> showAll = new ObservableElement<>(false);
@@ -77,7 +77,7 @@ public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkVi
     private OnBufferClickListener bufferClickListener;
     private ActionModeHandler actionModeHandler;
 
-    private BufferViewConfigAdapter(AppContext context, ObservableSortedList<NetworkItem> items) {
+    private BufferViewConfigAdapter(AppContext context, AndroidObservableSortedList<NetworkItem> items) {
         super(items);
         this.context = context;
         this.items = items;
@@ -135,7 +135,7 @@ public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkVi
     }
 
     public static BufferViewConfigAdapter of(AppContext context) {
-        final ObservableSortedList<NetworkItem> networkItems = new ObservableSortedList<>(NetworkItem.class, new ObservableSortedList.ItemComparator<NetworkItem>() {
+        final AndroidObservableSortedList<NetworkItem> networkItems = new AndroidObservableSortedList<>(NetworkItem.class, new AndroidObservableSortedList.ItemComparator<NetworkItem>() {
             @Override
             public int compare(NetworkItem o1, NetworkItem o2) {
                 assertNotNull(o1);
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
index 042de87f7..3c94f537e 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
@@ -23,7 +23,7 @@ package de.kuschku.quasseldroid_ng.ui.chat.drawer;
 
 import com.bignerdranch.expandablerecyclerview.Model.ParentListItem;
 
-import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
 
 import de.kuschku.libquassel.localtypes.buffers.Buffer;
@@ -31,6 +31,7 @@ import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+import de.kuschku.util.irc.IrcCaseMappers;
 import de.kuschku.util.observables.callbacks.ElementCallback;
 import de.kuschku.util.observables.callbacks.UICallback;
 import de.kuschku.util.observables.lists.ObservableSet;
@@ -40,12 +41,12 @@ public class NetworkItem implements ParentListItem {
     private final AppContext context;
     private final QBufferViewConfig config;
     private final QNetwork network;
-    private final List<Buffer> bufferList = new ArrayList<>();
-    private final ObservableSortedList<Buffer> buffers = new ObservableSortedList<>(Buffer.class, new ObservableSortedList.ItemComparator<Buffer>() {
+    private final ObservableSortedList<Buffer> buffers = new ObservableSortedList<>(new Comparator<Buffer>() {
         @Override
         public int compare(Buffer o1, Buffer o2) {
             if (o1.getInfo().type == o2.getInfo().type) {
-                return network.caseMapper().toLowerCase(o1.getName()).compareTo(network.caseMapper().toLowerCase(o2.getName()));
+                IrcCaseMappers.IrcCaseMapper ircCaseMapper = network.caseMapper();
+                return ircCaseMapper.toLowerCase(o1.getName()).compareTo(ircCaseMapper.toLowerCase(o2.getName()));
             } else {
                 if (o1.getInfo().type == BufferInfo.Type.STATUS)
                     return -1;
@@ -63,16 +64,6 @@ public class NetworkItem implements ParentListItem {
                     return -1;
             }
         }
-
-        @Override
-        public boolean areContentsTheSame(Buffer oldItem, Buffer newItem) {
-            return oldItem == newItem;
-        }
-
-        @Override
-        public boolean areItemsTheSame(Buffer item1, Buffer item2) {
-            return item1.getInfo().id == item2.getInfo().id;
-        }
     });
     private final ElementCallback<Integer> callback = new ElementCallback<Integer>() {
         @Override
@@ -80,7 +71,6 @@ public class NetworkItem implements ParentListItem {
             Buffer buffer = context.client().bufferManager().buffer(element);
             if (buffer != null && buffer.getInfo().networkId == network.networkId()) {
                 buffers.add(buffer);
-                bufferList.add(buffers.indexOf(buffer), buffer);
             }
         }
 
@@ -88,8 +78,7 @@ public class NetworkItem implements ParentListItem {
         public void notifyItemRemoved(Integer element) {
             Buffer buffer = context.client().bufferManager().buffer(element);
             if (buffer != null && buffer.getInfo().networkId == network.networkId()) {
-                buffers.remove(bufferList.indexOf(buffer));
-                bufferList.remove(buffer);
+                buffers.remove(buffer);
             }
         }
 
@@ -160,16 +149,8 @@ public class NetworkItem implements ParentListItem {
             @Override
             public void notifyItemChanged(Integer element) {
                 Buffer buffer = NetworkItem.this.context.client().bufferManager().buffer(element);
-                if (buffer != null && buffer.getInfo().networkId == NetworkItem.this.network.networkId() && bufferList.contains(buffer)) {
-                    int position = buffers.indexOf(buffer);
-                    if (position == -1) {
-                        buffers.remove(bufferList.indexOf(buffer));
-                        bufferList.remove(buffer);
-                        buffers.add(buffer);
-                        bufferList.add(buffers.indexOf(buffer), buffer);
-                    } else {
-                        buffers.notifyItemChanged(position);
-                    }
+                if (buffer != null && buffer.getInfo().networkId == NetworkItem.this.network.networkId() && buffers.contains(buffer)) {
+                    buffers.notifyItemChanged(buffer);
                 }
             }
         });
@@ -179,14 +160,12 @@ public class NetworkItem implements ParentListItem {
         if (this.backingSet != null)
             this.backingSet.removeCallback(callback);
         buffers.clear();
-        bufferList.clear();
 
         backingSet.addCallback(callback);
         for (int id : backingSet) {
             Buffer buffer = context.client().bufferManager().buffer(id);
             if (buffer != null && buffer.getInfo().networkId == network.networkId()) {
                 buffers.add(buffer);
-                bufferList.add(buffers.indexOf(buffer), buffer);
             }
         }
         this.backingSet = backingSet;
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java
index 2eac770c6..84d9bfa68 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java
@@ -49,7 +49,7 @@ import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread;
 import de.kuschku.quasseldroid_ng.ui.chat.chatview.MessageAdapter;
 import de.kuschku.quasseldroid_ng.ui.chat.util.SlidingPanelHandler;
 import de.kuschku.util.observables.AutoScroller;
-import de.kuschku.util.observables.lists.ObservableComparableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableComparableSortedList;
 import de.kuschku.util.servicebound.BoundFragment;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
@@ -124,7 +124,7 @@ public class ChatFragment extends BoundFragment {
         if (client != null && client.connectionStatus() == ConnectionChangeEvent.Status.CONNECTED) {
             QBacklogManager backlogManager = client.backlogManager();
             int id = backlogManager.open();
-            ObservableComparableSortedList<Message> messageList = backlogManager.filtered(id);
+            AndroidObservableComparableSortedList<Message> messageList = backlogManager.filtered(id);
             messageAdapter.setMessageList(messageList);
         }
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/nicklist/NickListAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/nicklist/NickListAdapter.java
index 09c34fcc8..f5102ad57 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/nicklist/NickListAdapter.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/nicklist/NickListAdapter.java
@@ -28,8 +28,7 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Comparator;
 
 import butterknife.Bind;
 import butterknife.ButterKnife;
@@ -38,7 +37,6 @@ import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 import de.kuschku.quasseldroid_ng.R;
 import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
 import de.kuschku.util.CompatibilityUtils;
-import de.kuschku.util.backports.Objects;
 import de.kuschku.util.observables.callbacks.ElementCallback;
 import de.kuschku.util.observables.callbacks.wrappers.AdapterUICallbackWrapper;
 import de.kuschku.util.observables.lists.ObservableSortedList;
@@ -49,8 +47,7 @@ public class NickListAdapter extends RecyclerView.Adapter<NickListAdapter.NickVi
     private final AppContext context;
     QIrcChannel channel;
 
-    List<QIrcUser> list = new ArrayList<>();
-    ObservableSortedList<QIrcUser> users = new ObservableSortedList<>(QIrcUser.class, new ObservableSortedList.ItemComparator<QIrcUser>() {
+    ObservableSortedList<QIrcUser> users = new ObservableSortedList<>(new Comparator<QIrcUser>() {
         @Override
         public int compare(QIrcUser o1, QIrcUser o2) {
             if (channel.userModes(o1).equals(channel.userModes(o2))) {
@@ -59,23 +56,12 @@ public class NickListAdapter extends RecyclerView.Adapter<NickListAdapter.NickVi
                 return channel.network().lowestModeIndex(channel.userModes(o1)) - channel.network().lowestModeIndex(channel.userModes(o2));
             }
         }
-
-        @Override
-        public boolean areContentsTheSame(QIrcUser oldItem, QIrcUser newItem) {
-            return Objects.equals(oldItem.userModes(), newItem.userModes()) && Objects.equals(oldItem.realName(), newItem.realName());
-        }
-
-        @Override
-        public boolean areItemsTheSame(QIrcUser item1, QIrcUser item2) {
-            return Objects.equals(item1.nick(), item2.nick());
-        }
     });
     private ElementCallback<String> callback = new ElementCallback<String>() {
         @Override
         public void notifyItemInserted(String element) {
             QIrcUser qIrcUser = channel.network().ircUser(element);
             users.add(qIrcUser);
-            list.add(users.indexOf(qIrcUser), qIrcUser);
         }
 
         @Override
@@ -84,18 +70,15 @@ public class NickListAdapter extends RecyclerView.Adapter<NickListAdapter.NickVi
                 QIrcUser user = users.get(i);
                 if (user.nick().equals(element)) {
                     users.remove(i);
-                    list.remove(user);
                 }
             }
         }
 
         @Override
         public void notifyItemChanged(String element) {
-            QIrcUser object = channel.network().ircUser(element);
-            if (object != null) {
-                users.notifyItemChanged(list.indexOf(object));
-                list.remove(object);
-                list.add(users.indexOf(object), object);
+            QIrcUser user = channel.network().ircUser(element);
+            if (user != null) {
+                users.notifyItemChanged(user);
             }
         }
     };
@@ -110,13 +93,11 @@ public class NickListAdapter extends RecyclerView.Adapter<NickListAdapter.NickVi
             this.channel.users().removeCallback(callback);
         this.channel = channel;
         this.users.clear();
-        this.list.clear();
         if (this.channel != null) {
             for (String nick : channel.users()) {
                 QIrcUser ircUser = channel.network().ircUser(nick);
                 if (ircUser != null) {
                     users.add(ircUser);
-                    list.add(users.indexOf(ircUser), ircUser);
                 }
             }
             this.channel.users().addCallback(callback);
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentitySpinnerAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentitySpinnerAdapter.java
index fc1721c0f..27ca73fbe 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentitySpinnerAdapter.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentitySpinnerAdapter.java
@@ -39,11 +39,11 @@ import de.kuschku.libquassel.syncables.types.interfaces.QIdentity;
 import de.kuschku.quasseldroid_ng.R;
 import de.kuschku.util.observables.callbacks.GeneralCallback;
 import de.kuschku.util.observables.callbacks.UICallback;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 public class IdentitySpinnerAdapter implements ThemedSpinnerAdapter, GeneralCallback {
     private final Set<DataSetObserver> observers = new HashSet<>();
-    private ObservableSortedList<QIdentity> identities;
+    private AndroidObservableSortedList<QIdentity> identities;
     @Nullable
     private Resources.Theme theme;
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/FakeNetworksWrapper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/FakeNetworksWrapper.java
index bf010533e..6dc69af1b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/FakeNetworksWrapper.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/FakeNetworksWrapper.java
@@ -29,7 +29,7 @@ import java.util.Set;
 
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.util.observables.callbacks.UICallback;
-import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.observables.lists.AndroidObservableSortedList;
 
 public class FakeNetworksWrapper {
     private final QNetwork fakeNetwork;
@@ -70,13 +70,13 @@ public class FakeNetworksWrapper {
             notifyChanged();
         }
     };
-    private ObservableSortedList<QNetwork> base;
+    private AndroidObservableSortedList<QNetwork> base;
 
     public FakeNetworksWrapper(Context context) {
         this.fakeNetwork = new AllNetworksItem(context);
     }
 
-    public void setBase(ObservableSortedList<QNetwork> base) {
+    public void setBase(AndroidObservableSortedList<QNetwork> base) {
         if (this.base != null)
             this.base.removeCallback(callback);
         this.base = base;
diff --git a/app/src/main/java/de/kuschku/util/observables/lists/AndroidObservableComparableSortedList.java b/app/src/main/java/de/kuschku/util/observables/lists/AndroidObservableComparableSortedList.java
new file mode 100644
index 000000000..47adf2fde
--- /dev/null
+++ b/app/src/main/java/de/kuschku/util/observables/lists/AndroidObservableComparableSortedList.java
@@ -0,0 +1,58 @@
+/*
+ * QuasselDroid - Quassel client for Android
+ * Copyright (C) 2016 Janne Koschinski
+ * Copyright (C) 2016 Ken Børge Viktil
+ * Copyright (C) 2016 Magnus Fjell
+ * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org>
+ *
+ * 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 de.kuschku.util.observables.lists;
+
+import android.support.annotation.NonNull;
+
+import java.util.List;
+
+import de.kuschku.util.observables.ContentComparable;
+import de.kuschku.util.observables.callbacks.UICallback;
+
+public class AndroidObservableComparableSortedList<T extends ContentComparable<T>> extends AndroidObservableSortedList<T> implements IObservableList<UICallback, T>, List<T> {
+
+
+    public AndroidObservableComparableSortedList(@NonNull Class<T> cl) {
+        super(cl, new SimpleItemComparator<>());
+    }
+
+    public AndroidObservableComparableSortedList(@NonNull Class<T> cl, boolean reverse) {
+        super(cl, new SimpleItemComparator<>(), reverse);
+    }
+
+    public static class SimpleItemComparator<T extends ContentComparable<T>> implements ItemComparator<T> {
+        @Override
+        public int compare(@NonNull T o1, @NonNull T o2) {
+            return o1.compareTo(o2);
+        }
+
+        @Override
+        public boolean areContentsTheSame(@NonNull T oldItem, @NonNull T newItem) {
+            return oldItem.areContentsTheSame(newItem);
+        }
+
+        @Override
+        public boolean areItemsTheSame(@NonNull T item1, @NonNull T item2) {
+            return item1.areItemsTheSame(item2);
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/util/observables/lists/AndroidObservableSortedList.java b/app/src/main/java/de/kuschku/util/observables/lists/AndroidObservableSortedList.java
new file mode 100644
index 000000000..95951037d
--- /dev/null
+++ b/app/src/main/java/de/kuschku/util/observables/lists/AndroidObservableSortedList.java
@@ -0,0 +1,372 @@
+/*
+ * QuasselDroid - Quassel client for Android
+ * Copyright (C) 2016 Janne Koschinski
+ * Copyright (C) 2016 Ken Børge Viktil
+ * Copyright (C) 2016 Magnus Fjell
+ * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@kde.org>
+ *
+ * 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 de.kuschku.util.observables.lists;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.util.SortedList;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import de.kuschku.util.backports.Stream;
+import de.kuschku.util.observables.callbacks.UICallback;
+import de.kuschku.util.observables.callbacks.wrappers.MultiUICallbackWrapper;
+
+import static de.kuschku.util.AndroidAssert.assertTrue;
+
+@SuppressWarnings("unchecked")
+public class AndroidObservableSortedList<T> implements IObservableList<UICallback, T> {
+    @NonNull
+    private final SortedList<T> list;
+    private final boolean reverse;
+
+    @NonNull
+    private final MultiUICallbackWrapper callback = MultiUICallbackWrapper.of();
+    @NonNull
+    private ItemComparator<T> comparator;
+
+    public AndroidObservableSortedList(@NonNull Class<T> cl, @NonNull ItemComparator<T> comparator) {
+        this(cl, comparator, false);
+    }
+
+    public AndroidObservableSortedList(@NonNull Class<T> cl, @NonNull ItemComparator<T> comparator, boolean reverse) {
+        this.list = new SortedList<>(cl, new Callback());
+        this.comparator = comparator;
+        this.reverse = reverse;
+    }
+
+    @Override
+    public void addCallback(@NonNull UICallback callback) {
+        this.callback.addCallback(callback);
+    }
+
+    @Override
+    public void removeCallback(@NonNull UICallback callback) {
+        this.callback.removeCallback(callback);
+    }
+
+    @Override
+    public void removeCallbacks() {
+        callback.removeCallbacks();
+    }
+
+    public void setComparator(@NonNull ItemComparator<T> comparator) {
+        this.comparator = comparator;
+    }
+
+    @Nullable
+    public T last() {
+        if (list.size() == 0) return null;
+
+        return list.get(list.size() - 1);
+    }
+
+    @Override
+    public void add(int location, T object) {
+        list.add(object);
+    }
+
+    @Override
+    public boolean add(T object) {
+        list.add(object);
+        return true;
+    }
+
+    @Override
+    public boolean addAll(int location, @NonNull Collection<? extends T> collection) {
+        list.addAll((Collection<T>) collection);
+        return true;
+    }
+
+    @Override
+    public boolean addAll(@NonNull Collection<? extends T> collection) {
+        list.addAll((Collection<T>) collection);
+        return false;
+    }
+
+    @Override
+    public void clear() {
+        list.clear();
+    }
+
+    @Override
+    public boolean contains(Object object) {
+        return indexOf(object) != SortedList.INVALID_POSITION;
+    }
+
+    @Override
+    public boolean containsAll(@NonNull Collection<?> collection) {
+        return new Stream<>(collection).allMatch(this::contains);
+    }
+
+    @Override
+    public T get(int location) {
+        return list.get(location);
+    }
+
+    @Override
+    public int indexOf(Object object) {
+        return list.indexOf((T) object);
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return list.size() == 0;
+    }
+
+    @NonNull
+    @Override
+    public Iterator<T> iterator() {
+        return new CallbackedSortedListIterator();
+    }
+
+    @Override
+    public int lastIndexOf(Object object) {
+        return indexOf(object);
+    }
+
+    @NonNull
+    @Override
+    public ListIterator<T> listIterator() {
+        return new CallbackedSortedListIterator();
+    }
+
+    @NonNull
+    @Override
+    public ListIterator<T> listIterator(int location) {
+        return new CallbackedSortedListIterator(location);
+    }
+
+    @Nullable
+    @Override
+    public T remove(int location) {
+        T item = list.get(location);
+        list.remove(item);
+        return item;
+    }
+
+    @Override
+    public boolean remove(Object object) {
+        try {
+            list.remove((T) object);
+            return true;
+        } catch (ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean removeAll(@NonNull Collection<?> collection) {
+        boolean result = true;
+        for (Object o : collection) {
+            result &= remove(o);
+        }
+        return result;
+    }
+
+    @Override
+    public boolean retainAll(@NonNull Collection<?> collection) {
+        return false;
+    }
+
+    @Nullable
+    @Override
+    public T set(int location, T object) {
+        return null;
+    }
+
+    @Override
+    public int size() {
+        return list.size();
+    }
+
+    @NonNull
+    @Override
+    public List<T> subList(int start, int end) {
+        assertTrue(start <= end);
+        assertTrue(start >= 0);
+        assertTrue(end <= list.size());
+
+        List<T> subList = new ArrayList<>(end - start);
+        for (int i = start; i < end; i++) {
+            subList.add(list.get(i));
+        }
+        return subList;
+    }
+
+    @NonNull
+    @Override
+    public Object[] toArray() {
+        Object[] array = new Object[list.size()];
+        for (int i = 0; i < list.size(); i++) {
+            array[i] = list.get(i);
+        }
+        return array;
+    }
+
+    @NonNull
+    @Override
+    public <T1> T1[] toArray(@NonNull T1[] a) {
+        try {
+            Object[] elements = toArray();
+            if (a.length < elements.length)
+                // Make a new array of a's runtime type, but my contents:
+                return (T1[]) Arrays.copyOf(elements, elements.length, a.getClass());
+            System.arraycopy(elements, 0, a, 0, elements.length);
+            if (a.length > elements.length)
+                a[elements.length] = null;
+            return a;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void notifyItemChanged(int position) {
+        T obj = get(position);
+        list.recalculatePositionOfItemAt(position);
+        callback.notifyItemChanged(indexOf(obj));
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return Arrays.toString(toArray());
+    }
+
+    public interface ItemComparator<T> {
+        int compare(T o1, T o2);
+
+        boolean areContentsTheSame(T oldItem, T newItem);
+
+        boolean areItemsTheSame(T item1, T item2);
+    }
+
+    class Callback extends SortedList.Callback<T> {
+        @Override
+        public int compare(T o1, T o2) {
+            return (reverse) ? comparator.compare(o2, o1) : comparator.compare(o1, o2);
+        }
+
+        @Override
+        public void onInserted(int position, int count) {
+            if (count == 1)
+                callback.notifyItemInserted(position);
+            else
+                callback.notifyItemRangeInserted(position, count);
+        }
+
+        @Override
+        public void onRemoved(int position, int count) {
+            if (count == 1)
+                callback.notifyItemRemoved(position);
+            else
+                callback.notifyItemRangeRemoved(position, count);
+        }
+
+        @Override
+        public void onMoved(int fromPosition, int toPosition) {
+            callback.notifyItemMoved(fromPosition, toPosition);
+        }
+
+        @Override
+        public void onChanged(int position, int count) {
+            if (count == 1)
+                callback.notifyItemChanged(position);
+            else
+                callback.notifyItemRangeChanged(position, count);
+        }
+
+        @Override
+        public boolean areContentsTheSame(T oldItem, T newItem) {
+            return comparator.areContentsTheSame(oldItem, newItem);
+        }
+
+        @Override
+        public boolean areItemsTheSame(T item1, T item2) {
+            return comparator.areItemsTheSame(item1, item2);
+        }
+    }
+
+    class CallbackedSortedListIterator implements Iterator<T>, ListIterator<T> {
+        int position;
+
+        public CallbackedSortedListIterator() {
+            this(0);
+        }
+
+        public CallbackedSortedListIterator(int position) {
+            this.position = position;
+        }
+
+        @Override
+        public void add(T object) {
+            list.add(object);
+        }
+
+        @Override
+        public boolean hasNext() {
+            return position < list.size();
+        }
+
+        @Override
+        public boolean hasPrevious() {
+            return position >= 0;
+        }
+
+        @Override
+        public T next() {
+            return list.get(position++);
+        }
+
+        @Override
+        public int nextIndex() {
+            return position + 1;
+        }
+
+        @Override
+        public T previous() {
+            return list.get(position--);
+        }
+
+        @Override
+        public int previousIndex() {
+            return position - 1;
+        }
+
+        @Override
+        public void remove() {
+            list.remove(list.get(position));
+            callback.notifyItemRemoved(position);
+        }
+
+        @Override
+        public void set(T object) {
+            list.remove(list.get(position));
+            list.add(object);
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/util/observables/lists/ChildParentObservableSortedList.java b/app/src/main/java/de/kuschku/util/observables/lists/ChildParentAndroidObservableSortedList.java
similarity index 87%
rename from app/src/main/java/de/kuschku/util/observables/lists/ChildParentObservableSortedList.java
rename to app/src/main/java/de/kuschku/util/observables/lists/ChildParentAndroidObservableSortedList.java
index 483cf25d2..5228011d2 100644
--- a/app/src/main/java/de/kuschku/util/observables/lists/ChildParentObservableSortedList.java
+++ b/app/src/main/java/de/kuschku/util/observables/lists/ChildParentAndroidObservableSortedList.java
@@ -30,16 +30,16 @@ import de.kuschku.util.observables.callbacks.UIParentCallback;
 import de.kuschku.util.observables.callbacks.wrappers.MultiUIChildParentCallback;
 import de.kuschku.util.observables.callbacks.wrappers.ParentUICallbackWrapper;
 
-public class ChildParentObservableSortedList<T extends IObservable<UIChildCallback>> extends ObservableSortedList<T> {
+public class ChildParentAndroidObservableSortedList<T extends IObservable<UIChildCallback>> extends AndroidObservableSortedList<T> {
     @NonNull
     private final MultiUIChildParentCallback callback = MultiUIChildParentCallback.of();
 
-    public ChildParentObservableSortedList(@NonNull Class<T> cl, @NonNull ItemComparator<T> comparator) {
+    public ChildParentAndroidObservableSortedList(@NonNull Class<T> cl, @NonNull ItemComparator<T> comparator) {
         super(cl, comparator);
         registerCallbacks();
     }
 
-    public ChildParentObservableSortedList(@NonNull Class<T> cl, @NonNull ItemComparator<T> comparator, boolean reverse) {
+    public ChildParentAndroidObservableSortedList(@NonNull Class<T> cl, @NonNull ItemComparator<T> comparator, boolean reverse) {
         super(cl, comparator, reverse);
         registerCallbacks();
     }
diff --git a/app/src/main/java/de/kuschku/util/observables/lists/ObservableComparableSortedList.java b/app/src/main/java/de/kuschku/util/observables/lists/ObservableComparableSortedList.java
index ddbc9a149..a241e1238 100644
--- a/app/src/main/java/de/kuschku/util/observables/lists/ObservableComparableSortedList.java
+++ b/app/src/main/java/de/kuschku/util/observables/lists/ObservableComparableSortedList.java
@@ -21,38 +21,36 @@
 
 package de.kuschku.util.observables.lists;
 
-import android.support.annotation.NonNull;
+import java.util.Comparator;
 
-import java.util.List;
-
-import de.kuschku.util.observables.ContentComparable;
 import de.kuschku.util.observables.callbacks.UICallback;
 
-public class ObservableComparableSortedList<T extends ContentComparable<T>> extends ObservableSortedList<T> implements IObservableList<UICallback, T>, List<T> {
-
-
-    public ObservableComparableSortedList(@NonNull Class<T> cl) {
-        super(cl, new SimpleItemComparator<>());
+public class ObservableComparableSortedList<T extends Comparable<? super T>> extends ObservableSortedList<T> implements IObservableList<UICallback, T> {
+    public ObservableComparableSortedList() {
+        super(new ComparableComparator<>());
     }
 
-    public ObservableComparableSortedList(@NonNull Class<T> cl, boolean reverse) {
-        super(cl, new SimpleItemComparator<>(), reverse);
+    public ObservableComparableSortedList(int capacity) {
+        super(new ComparableComparator<>(), capacity);
     }
 
-    public static class SimpleItemComparator<T extends ContentComparable<T>> implements ItemComparator<T> {
+    public static class ComparableComparator<T extends Comparable<? super T>> implements Comparator<T> {
         @Override
-        public int compare(@NonNull T o1, @NonNull T o2) {
+        public int compare(T o1, T o2) {
             return o1.compareTo(o2);
         }
+    }
 
-        @Override
-        public boolean areContentsTheSame(@NonNull T oldItem, @NonNull T newItem) {
-            return oldItem.areContentsTheSame(newItem);
+    public static class ItemComparatorWrapper<T> implements Comparator<T> {
+        private final AndroidObservableSortedList.ItemComparator<T> itemComparator;
+
+        public ItemComparatorWrapper(AndroidObservableSortedList.ItemComparator<T> itemComparator) {
+            this.itemComparator = itemComparator;
         }
 
         @Override
-        public boolean areItemsTheSame(@NonNull T item1, @NonNull T item2) {
-            return item1.areItemsTheSame(item2);
+        public int compare(T o1, T o2) {
+            return itemComparator.compare(o1, o2);
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/util/observables/lists/ObservableSortedList.java b/app/src/main/java/de/kuschku/util/observables/lists/ObservableSortedList.java
index 68ad2a8f3..0fea481ab 100644
--- a/app/src/main/java/de/kuschku/util/observables/lists/ObservableSortedList.java
+++ b/app/src/main/java/de/kuschku/util/observables/lists/ObservableSortedList.java
@@ -22,49 +22,40 @@
 package de.kuschku.util.observables.lists;
 
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v7.util.SortedList;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
 
-import de.kuschku.util.backports.Stream;
 import de.kuschku.util.observables.callbacks.UICallback;
 import de.kuschku.util.observables.callbacks.wrappers.MultiUICallbackWrapper;
 
-import static de.kuschku.util.AndroidAssert.assertTrue;
-
-@SuppressWarnings("unchecked")
-public class ObservableSortedList<T> implements IObservableList<UICallback, T> {
-    @NonNull
-    private final SortedList<T> list;
-    private final boolean reverse;
-
+public class ObservableSortedList<T> extends ArrayList<T> implements IObservableList<UICallback, T> {
     @NonNull
     private final MultiUICallbackWrapper callback = MultiUICallbackWrapper.of();
-    @NonNull
-    private ItemComparator<T> comparator;
 
-    public ObservableSortedList(@NonNull Class<T> cl, @NonNull ItemComparator<T> comparator) {
-        this(cl, comparator, false);
+    private final Comparator<T> comparator;
+
+    public ObservableSortedList(Comparator<T> comparator) {
+        super();
+        this.comparator = comparator;
     }
 
-    public ObservableSortedList(@NonNull Class<T> cl, @NonNull ItemComparator<T> comparator, boolean reverse) {
-        this.list = new SortedList<>(cl, new Callback());
+    public ObservableSortedList(Comparator<T> comparator, int capacity) {
+        super(capacity);
         this.comparator = comparator;
-        this.reverse = reverse;
     }
 
-    @Override
+    public ObservableSortedList(AndroidObservableSortedList.ItemComparator<T> itemComparator) {
+        this.comparator = new ObservableComparableSortedList.ItemComparatorWrapper<>(itemComparator);
+    }
+
     public void addCallback(@NonNull UICallback callback) {
         this.callback.addCallback(callback);
     }
 
-    @Override
     public void removeCallback(@NonNull UICallback callback) {
         this.callback.removeCallback(callback);
     }
@@ -74,299 +65,148 @@ public class ObservableSortedList<T> implements IObservableList<UICallback, T> {
         callback.removeCallbacks();
     }
 
-    public void setComparator(@NonNull ItemComparator<T> comparator) {
-        this.comparator = comparator;
-    }
-
-    @Nullable
-    public T last() {
-        if (list.size() == 0) return null;
+    private int getPosition(T key) {
+        int low = 0;
+        int high = size() - 1;
 
-        return list.get(list.size() - 1);
-    }
+        while (low <= high) {
+            int mid = (low + high) >>> 1;
+            T midVal = get(mid);
+            int cmp = comparator.compare(midVal, key);
 
-    @Override
-    public void add(int location, T object) {
-        list.add(object);
+            if (cmp < 0)
+                low = mid + 1;
+            else if (cmp > 0)
+                high = mid - 1;
+            else
+                return -1; // key found
+        }
+        return low;  // key not found
     }
 
     @Override
     public boolean add(T object) {
-        list.add(object);
-        return true;
-    }
-
-    @Override
-    public boolean addAll(int location, @NonNull Collection<? extends T> collection) {
-        list.addAll((Collection<T>) collection);
-        return true;
+        int position = addInternal(object);
+        callback.notifyItemInserted(position);
+        return position != -1;
     }
 
-    @Override
-    public boolean addAll(@NonNull Collection<? extends T> collection) {
-        list.addAll((Collection<T>) collection);
-        return false;
+    public int addInternal(T object) {
+        int position = getPosition(object);
+        if (position != -1) super.add(position, object);
+        return position;
     }
 
     @Override
-    public void clear() {
-        list.clear();
+    public void add(int index, T object) {
+        add(object);
     }
 
     @Override
-    public boolean contains(Object object) {
-        return indexOf(object) != SortedList.INVALID_POSITION;
-    }
-
-    @Override
-    public boolean containsAll(@NonNull Collection<?> collection) {
-        return new Stream<>(collection).allMatch(this::contains);
-    }
-
-    @Override
-    public T get(int location) {
-        return list.get(location);
-    }
-
-    @Override
-    public int indexOf(Object object) {
-        return list.indexOf((T) object);
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return list.size() == 0;
-    }
-
-    @NonNull
-    @Override
-    public Iterator<T> iterator() {
-        return new CallbackedSortedListIterator();
-    }
-
-    @Override
-    public int lastIndexOf(Object object) {
-        return indexOf(object);
-    }
-
-    @NonNull
-    @Override
-    public ListIterator<T> listIterator() {
-        return new CallbackedSortedListIterator();
+    public boolean addAll(@NonNull Collection<? extends T> collection) {
+        boolean addedAny = false;
+        for (T t : collection) {
+            addedAny |= add(t);
+        }
+        return addedAny;
     }
 
-    @NonNull
     @Override
-    public ListIterator<T> listIterator(int location) {
-        return new CallbackedSortedListIterator(location);
+    public boolean addAll(int index, @NonNull Collection<? extends T> collection) {
+        return addAll(collection);
     }
 
-    @Nullable
     @Override
-    public T remove(int location) {
-        T item = list.get(location);
-        list.remove(item);
-        return item;
+    public T remove(int index) {
+        T result = super.remove(index);
+        callback.notifyItemRemoved(index);
+        return result;
     }
 
     @Override
     public boolean remove(Object object) {
-        try {
-            list.remove((T) object);
-            return true;
-        } catch (ClassCastException e) {
+        int position = indexOf(object);
+        if (position == -1) {
             return false;
+        } else {
+            remove(position);
+            return true;
         }
     }
 
     @Override
-    public boolean removeAll(@NonNull Collection<?> collection) {
-        boolean result = true;
-        for (Object o : collection) {
-            result &= remove(o);
-        }
-        return result;
-    }
-
-    @Override
-    public boolean retainAll(@NonNull Collection<?> collection) {
-        return false;
+    protected void removeRange(int fromIndex, int toIndex) {
+        super.removeRange(fromIndex, toIndex);
+        callback.notifyItemRangeRemoved(fromIndex, toIndex - fromIndex);
     }
 
-    @Nullable
     @Override
-    public T set(int location, T object) {
-        return null;
+    public int indexOf(Object object) {
+        return Collections.binarySearch(this, (T) object, comparator);
     }
 
     @Override
-    public int size() {
-        return list.size();
+    public int lastIndexOf(Object object) {
+        return Collections.binarySearch(this, (T) object, comparator);
     }
 
-    @NonNull
     @Override
-    public List<T> subList(int start, int end) {
-        assertTrue(start <= end);
-        assertTrue(start >= 0);
-        assertTrue(end <= list.size());
-
-        List<T> subList = new ArrayList<>(end - start);
-        for (int i = start; i < end; i++) {
-            subList.add(list.get(i));
-        }
-        return subList;
+    public void clear() {
+        int size = size();
+        super.clear();
+        callback.notifyItemRangeRemoved(0, size);
     }
 
-    @NonNull
     @Override
-    public Object[] toArray() {
-        Object[] array = new Object[list.size()];
-        for (int i = 0; i < list.size(); i++) {
-            array[i] = list.get(i);
-        }
-        return array;
+    public T set(int index, T element) {
+        T set = super.set(index, element);
+        notifyItemChanged(element);
+        callback.notifyItemChanged(index);
+        return set;
     }
 
-    @NonNull
-    @Override
-    public <T1> T1[] toArray(@NonNull T1[] a) {
-        try {
-            Object[] elements = toArray();
-            if (a.length < elements.length)
-                // Make a new array of a's runtime type, but my contents:
-                return (T1[]) Arrays.copyOf(elements, elements.length, a.getClass());
-            System.arraycopy(elements, 0, a, 0, elements.length);
-            if (a.length > elements.length)
-                a[elements.length] = null;
-            return a;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+    public void notifyItemChanged(T element) {
+        int index = super.indexOf(element);
+        super.remove(index);
+        int position = getPosition(element);
+        if (position != index) {
+            callback.notifyItemRemoved(index);
+            add(position, element);
+        } else {
+            super.add(index, element);
+            callback.notifyItemChanged(index);
         }
     }
 
-    public void notifyItemChanged(int position) {
-        T obj = get(position);
-        list.recalculatePositionOfItemAt(position);
-        callback.notifyItemChanged(indexOf(obj));
-    }
-
     @NonNull
     @Override
-    public String toString() {
-        return Arrays.toString(toArray());
-    }
-
-    public interface ItemComparator<T> {
-        int compare(T o1, T o2);
-
-        boolean areContentsTheSame(T oldItem, T newItem);
-
-        boolean areItemsTheSame(T item1, T item2);
-    }
-
-    class Callback extends SortedList.Callback<T> {
-        @Override
-        public int compare(T o1, T o2) {
-            return (reverse) ? comparator.compare(o2, o1) : comparator.compare(o1, o2);
-        }
-
-        @Override
-        public void onInserted(int position, int count) {
-            if (count == 1)
-                callback.notifyItemInserted(position);
-            else
-                callback.notifyItemRangeInserted(position, count);
-        }
-
-        @Override
-        public void onRemoved(int position, int count) {
-            if (count == 1)
-                callback.notifyItemRemoved(position);
-            else
-                callback.notifyItemRangeRemoved(position, count);
-        }
-
-        @Override
-        public void onMoved(int fromPosition, int toPosition) {
-            callback.notifyItemMoved(fromPosition, toPosition);
-        }
-
-        @Override
-        public void onChanged(int position, int count) {
-            if (count == 1)
-                callback.notifyItemChanged(position);
-            else
-                callback.notifyItemRangeChanged(position, count);
-        }
-
-        @Override
-        public boolean areContentsTheSame(T oldItem, T newItem) {
-            return comparator.areContentsTheSame(oldItem, newItem);
-        }
-
-        @Override
-        public boolean areItemsTheSame(T item1, T item2) {
-            return comparator.areItemsTheSame(item1, item2);
-        }
+    public Iterator<T> iterator() {
+        return new CallbackedArrayListIterator<>(super.iterator());
     }
 
-    class CallbackedSortedListIterator implements Iterator<T>, ListIterator<T> {
-        int position;
-
-        public CallbackedSortedListIterator() {
-            this(0);
-        }
+    class CallbackedArrayListIterator<E> implements Iterator<E> {
+        final Iterator<E> iterator;
+        int position = 0;
 
-        public CallbackedSortedListIterator(int position) {
-            this.position = position;
-        }
-
-        @Override
-        public void add(T object) {
-            list.add(object);
+        public CallbackedArrayListIterator(Iterator<E> iterator) {
+            this.iterator = iterator;
         }
 
         @Override
         public boolean hasNext() {
-            return position < list.size();
+            return iterator.hasNext();
         }
 
         @Override
-        public boolean hasPrevious() {
-            return position >= 0;
-        }
-
-        @Override
-        public T next() {
-            return list.get(position++);
-        }
-
-        @Override
-        public int nextIndex() {
-            return position + 1;
-        }
-
-        @Override
-        public T previous() {
-            return list.get(position--);
-        }
-
-        @Override
-        public int previousIndex() {
-            return position - 1;
+        public E next() {
+            position++;
+            return iterator.next();
         }
 
         @Override
         public void remove() {
-            list.remove(list.get(position));
+            iterator.remove();
             callback.notifyItemRemoved(position);
         }
-
-        @Override
-        public void set(T object) {
-            list.remove(list.get(position));
-            list.add(object);
-        }
     }
 }
diff --git a/app/src/main/res/layout/activity_alias_edit.xml b/app/src/main/res/layout/activity_alias_edit.xml
index df5b02c13..dc6fa4aae 100644
--- a/app/src/main/res/layout/activity_alias_edit.xml
+++ b/app/src/main/res/layout/activity_alias_edit.xml
@@ -23,6 +23,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
@@ -36,7 +37,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_channel_detail.xml b/app/src/main/res/layout/activity_channel_detail.xml
index d25e1eaa8..9037982d9 100644
--- a/app/src/main/res/layout/activity_channel_detail.xml
+++ b/app/src/main/res/layout/activity_channel_detail.xml
@@ -20,6 +20,7 @@
   -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:app="http://schemas.android.com/apk/res-auto"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:orientation="vertical">
@@ -33,7 +34,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_chatlist_edit.xml b/app/src/main/res/layout/activity_chatlist_edit.xml
index 243e05c1a..f58e9ea1e 100644
--- a/app/src/main/res/layout/activity_chatlist_edit.xml
+++ b/app/src/main/res/layout/activity_chatlist_edit.xml
@@ -37,7 +37,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_chatlist_list.xml b/app/src/main/res/layout/activity_chatlist_list.xml
index 71d52eb61..312273e20 100644
--- a/app/src/main/res/layout/activity_chatlist_list.xml
+++ b/app/src/main/res/layout/activity_chatlist_list.xml
@@ -36,7 +36,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_identity_edit.xml b/app/src/main/res/layout/activity_identity_edit.xml
index 1edeb64e2..ecd3265e1 100644
--- a/app/src/main/res/layout/activity_identity_edit.xml
+++ b/app/src/main/res/layout/activity_identity_edit.xml
@@ -23,6 +23,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
@@ -36,7 +37,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_ignorerule_edit.xml b/app/src/main/res/layout/activity_ignorerule_edit.xml
index 2a947c256..2e3394f94 100644
--- a/app/src/main/res/layout/activity_ignorerule_edit.xml
+++ b/app/src/main/res/layout/activity_ignorerule_edit.xml
@@ -37,7 +37,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_network_edit.xml b/app/src/main/res/layout/activity_network_edit.xml
index 936a509d1..85827f380 100644
--- a/app/src/main/res/layout/activity_network_edit.xml
+++ b/app/src/main/res/layout/activity_network_edit.xml
@@ -37,7 +37,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_network_list.xml b/app/src/main/res/layout/activity_network_list.xml
index 7f3dcc699..d49357519 100644
--- a/app/src/main/res/layout/activity_network_list.xml
+++ b/app/src/main/res/layout/activity_network_list.xml
@@ -36,7 +36,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_networkserver_edit.xml b/app/src/main/res/layout/activity_networkserver_edit.xml
index 947275caf..562ccaca0 100644
--- a/app/src/main/res/layout/activity_networkserver_edit.xml
+++ b/app/src/main/res/layout/activity_networkserver_edit.xml
@@ -37,7 +37,8 @@
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"/>
+            android:layout_height="?attr/actionBarSize"
+            app:contentInsetStartWithNavigation="0dp"/>
 
     </android.support.design.widget.AppBarLayout>
 
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index 799cfa876..099972e36 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -24,17 +24,19 @@
               android:layout_height="match_parent"
               android:orientation="vertical">
 
-    <android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                                                xmlns:app="http://schemas.android.com/apk/res-auto"
-                                                android:layout_width="match_parent"
-                                                android:layout_height="wrap_content"
-                                                android:theme="?attr/actionBarTheme">
+    <android.support.design.widget.AppBarLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:app="http://schemas.android.com/apk/res-auto"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:theme="?attr/actionBarTheme">
 
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
             android:background="?attr/colorPrimary"
+            app:contentInsetStartWithNavigation="0dp"
             app:popupTheme="@style/AppTheme.PopupOverlay"/>
 
     </android.support.design.widget.AppBarLayout>
diff --git a/app/src/main/res/layout/widget_actionbar.xml b/app/src/main/res/layout/widget_actionbar.xml
index 4ab110165..70e48d851 100644
--- a/app/src/main/res/layout/widget_actionbar.xml
+++ b/app/src/main/res/layout/widget_actionbar.xml
@@ -32,6 +32,7 @@
         android:layout_width="match_parent"
         android:layout_height="?attr/actionBarSize"
         android:background="?attr/colorPrimary"
+        app:contentInsetStartWithNavigation="0dp"
         app:popupTheme="@style/AppTheme.PopupOverlay">
 
         <LinearLayout
-- 
GitLab