diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcChannel.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcChannel.java
index 9c9bad616b958bc07746538aa1bad0cbd09514cc..3149c7c2044f0a1a56068051336718f51285fca0 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcChannel.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcChannel.java
@@ -43,6 +43,7 @@ import de.kuschku.libquassel.syncables.types.abstracts.AIrcChannel;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.util.irc.ModeUtils;
+import de.kuschku.util.observables.lists.ObservableSet;
 
 import static de.kuschku.util.AndroidAssert.assertEquals;
 
@@ -50,6 +51,7 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
     private final String name;
     @NonNull
     private final Map<QIrcUser, Set<Character>> userModes = new HashMap<>();
+    private final ObservableSet<QIrcUser> users = new ObservableSet<>();
     private String topic;
     private String password;
     private boolean encrypted;
@@ -285,6 +287,7 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
             _addUserMode(ircuser, mode);
         } else {
             userModes.put(ircuser, ModeUtils.toModes(mode));
+            users.add(ircuser);
             ircuser._joinChannel(this, true);
             _update();
         }
@@ -294,11 +297,13 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
     public void _part(@NonNull QIrcUser ircuser) {
         if (isKnownUser(ircuser)) {
             userModes.remove(ircuser);
+            users.remove(ircuser);
             ircuser._partChannel(this);
 
             if (network().isMe(ircuser) || userModes.isEmpty()) {
                 Set<QIrcUser> users = userModes.keySet();
                 userModes.clear();
+                users.clear();
                 for (QIrcUser user : users) {
                     user._partChannel(this, true);
                 }
@@ -318,6 +323,7 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
         if (isKnownUser(ircuser)) {
 
             userModes.put(ircuser, ModeUtils.toModes(modes));
+            users.add(ircuser);
             _update();
         }
     }
@@ -334,6 +340,7 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
 
         if (!userModes.get(ircuser).contains(ModeUtils.toMode(mode))) {
             userModes.get(ircuser).add(ModeUtils.toMode(mode));
+            users.notifyItemChanged(ircuser);
             _update();
         }
     }
@@ -421,9 +428,14 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
         this.network = network;
 
 
+        /* TODO: Use just the nick in userModes and users instead – that should make sync things a lot easier */
         if (cachedUserModes != null) {
             for (String username : cachedUserModes.keySet()) {
-                userModes.put(network().ircUser(username), ModeUtils.toModes(cachedUserModes.get(username)));
+                QIrcUser ircUser = network().ircUser(username);
+                if (ircUser != null) {
+                    userModes.put(ircUser, ModeUtils.toModes(cachedUserModes.get(username)));
+                    users.add(ircUser);
+                }
             }
         }
         if (cachedChanModes != null) {
@@ -483,4 +495,8 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
         assertEquals(split.length, 2);
         init(client.networkManager().network(Integer.parseInt(split[0])), client);
     }
+
+    public ObservableSet<QIrcUser> users() {
+        return users;
+    }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcUser.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcUser.java
index c76bb718cc6f1f43761c8b1bd422fc038f1734ce..e33a0e401f0a6a07d37dddf0691f750e987192d1 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcUser.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcUser.java
@@ -458,4 +458,9 @@ public class IrcUser extends AIrcUser<IrcUser> {
     @Override
     public void _update(IrcUser from) {
     }
+
+    @Override
+    public String toString() {
+        return "IrcUser{" + hostmask() + '}';
+    }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
index c062cf6e02d7feff4ff09e288eb3ff5397ba8c0a..b42e6bf9d0e4092203ab92be13124e72d3e18b00 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
@@ -41,6 +41,7 @@ import de.kuschku.libquassel.syncables.types.abstracts.ANetwork;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
+import de.kuschku.util.CompatibilityUtils;
 import de.kuschku.util.irc.IrcCaseMapper;
 import de.kuschku.util.irc.IrcUserUtils;
 import de.kuschku.util.irc.ModeUtils;
@@ -178,6 +179,12 @@ public class Network extends ANetwork<Network> implements Observer {
             return "";
     }
 
+    @Override
+    public int modeToIndex(String mode) {
+        int index = prefixModes().indexOf(mode);
+        return index == -1 ? Integer.MAX_VALUE : index;
+    }
+
     @Override
     public ChannelModeType channelModeType(char mode) {
         return channelModeType(ModeUtils.fromMode(mode));
@@ -334,11 +341,12 @@ public class Network extends ANetwork<Network> implements Observer {
         String prefix = support("PREFIX");
 
         if (prefix.startsWith("(") && prefix.contains(")")) {
-            prefixes = Arrays.asList(prefix.split("\\)")[1].split(""));
-            prefixModes = Arrays.asList(prefix.substring(1).split("\\)")[0].split(""));
+            String[] data = prefix.substring(1).split("\\)");
+            prefixes = Arrays.asList(CompatibilityUtils.partStringByChar(data[1]));
+            prefixModes = Arrays.asList(CompatibilityUtils.partStringByChar(data[0]));
         } else {
-            List<String> defaultPrefixes = Arrays.asList("~&@%+".split(""));
-            List<String> defaultPrefixModes = Arrays.asList("qaohv".split(""));
+            List<String> defaultPrefixes = Arrays.asList(CompatibilityUtils.partStringByChar("~&@%+"));
+            List<String> defaultPrefixModes = Arrays.asList(CompatibilityUtils.partStringByChar("qaohv"));
 
             if (prefix.isEmpty()) {
                 prefixes = defaultPrefixes;
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcChannel.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcChannel.java
index a1a406d57ff86814179f78db9e8fbd69d4323b5c..05486e16cd08b387dc5b6e08c375560eba188b15 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcChannel.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcChannel.java
@@ -27,6 +27,7 @@ import java.util.List;
 
 import de.kuschku.libquassel.client.Client;
 import de.kuschku.libquassel.syncables.Synced;
+import de.kuschku.util.observables.lists.ObservableSet;
 
 public interface QIrcChannel extends QObservable {
     boolean isKnownUser(QIrcUser ircuser);
@@ -148,4 +149,6 @@ public interface QIrcChannel extends QObservable {
     void init(QNetwork network, Client client);
 
     String getObjectName();
+
+    ObservableSet<QIrcUser> users();
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
index 5ea8da726ba7a2f04076d275fb9e3063d8cfdc9f..94093c47a627d465a4f12ba9c7cc4e0d8edca11f 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
@@ -55,6 +55,8 @@ public interface QNetwork extends QObservable {
 
     String modeToPrefix(final String mode);
 
+    int modeToIndex(String mode);
+
     ChannelModeType channelModeType(final char mode);
 
     ChannelModeType channelModeType(final String mode);
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java
index 07901428c7400286c8d2bd6254a13dc2f778509c..6c800d565699226a8ecd66a26098efc5e6828019 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java
@@ -32,6 +32,7 @@ import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.design.widget.Snackbar;
+import android.support.v4.view.GravityCompat;
 import android.support.v4.widget.SwipeRefreshLayout;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.ActionMenuView;
@@ -41,7 +42,9 @@ import android.support.v7.widget.DefaultItemAnimator;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.Toolbar;
+import android.text.SpannableString;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -107,6 +110,7 @@ import de.kuschku.util.instancestateutil.Storable;
 import de.kuschku.util.instancestateutil.Store;
 import de.kuschku.util.observables.AutoScroller;
 import de.kuschku.util.observables.lists.ObservableSortedList;
+import de.kuschku.util.ui.MessageUtil;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
@@ -148,8 +152,10 @@ public class ChatActivity extends AppCompatActivity {
     private MessageAdapter messageAdapter;
     private AccountHeader accountHeader;
     private Drawer drawerLeft;
+    private Drawer drawerRight;
     private AdvancedEditor editor;
     private BufferViewConfigItem wrapper;
+    private NickListWrapper nicklistwrapper;
     @Nullable
     private QuasselService.LocalBinder binder;
     @Nullable
@@ -499,6 +505,11 @@ public class ChatActivity extends AppCompatActivity {
                 return true;
             }
         });
+        drawerRight = new DrawerBuilder()
+                .withActivity(this)
+                .withSavedInstance(savedInstanceState)
+                .withDrawerGravity(Gravity.RIGHT)
+                .build();
     }
 
     private void setupHeader(@Nullable Bundle savedInstanceState) {
@@ -593,6 +604,12 @@ public class ChatActivity extends AppCompatActivity {
             messageAdapter.setMessageList(list);
             toolbar.setTitle(buffer.getName());
             updateNoColor(buffer, formattingMenu.getMenu());
+
+            if (buffer instanceof ChannelBuffer && ((ChannelBuffer) buffer).getChannel() != null) {
+                nicklistwrapper = new NickListWrapper(drawerRight, ((ChannelBuffer) buffer).getChannel());
+            } else {
+                drawerRight.removeAllItems();
+            }
         }
         updateSubTitle();
     }
@@ -619,6 +636,7 @@ public class ChatActivity extends AppCompatActivity {
         } else {
             Snackbar.make(messages, "No buffer opened", Snackbar.LENGTH_LONG).show();
         }
+        chatline.setVisibility(View.INVISIBLE);
     }
 
     public void onEventMainThread(@NonNull LoginRequireEvent event) {
@@ -759,7 +777,7 @@ public class ChatActivity extends AppCompatActivity {
 
     private void updateSubTitle() {
         if (context.client() != null) {
-            String subtitle;
+            CharSequence subtitle;
             if (context.client().connectionStatus() == ConnectionChangeEvent.Status.CONNECTED) {
                 if (status.bufferId >= 0) {
                     Buffer buffer = context.client().bufferManager().buffer(status.bufferId);
@@ -773,7 +791,11 @@ public class ChatActivity extends AppCompatActivity {
                         } else if (buffer instanceof ChannelBuffer) {
                             QIrcChannel channel = ((ChannelBuffer) buffer).getChannel();
                             if (channel != null)
-                                subtitle = channel.topic();
+                                subtitle = MessageUtil.parseStyleCodes(
+                                        context.themeUtil(),
+                                        channel.topic(),
+                                        context.settings().mircColors.or(true)
+                                );
                             else
                                 subtitle = "";
                         }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListWrapper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListWrapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..65a12afdc7c4ba0bc1c8b9452f4999081c13ee36
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListWrapper.java
@@ -0,0 +1,119 @@
+/*
+ * 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.quasseldroid_ng.ui.chat;
+
+import com.mikepenz.materialdrawer.Drawer;
+import com.mikepenz.materialdrawer.holder.BadgeStyle;
+import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
+import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
+
+import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
+import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
+import de.kuschku.util.backports.Objects;
+import de.kuschku.util.observables.callbacks.UICallback;
+import de.kuschku.util.observables.lists.ObservableSortedList;
+
+public class NickListWrapper {
+    private final QIrcChannel channel;
+    private ObservableSortedList<QIrcUser> list = new ObservableSortedList<>(QIrcUser.class, new ObservableSortedList.ItemComparator<QIrcUser>() {
+        @Override
+        public int compare(QIrcUser o1, QIrcUser o2) {
+            int indexa = channel.network().modeToIndex(channel.userModes(o1));
+            int indexb = channel.network().modeToIndex(channel.userModes(o2));
+            if (indexa == indexb) {
+                return o1.nick().compareToIgnoreCase(o2.nick());
+            } else {
+                return indexa - indexb;
+            }
+        }
+
+        @Override
+        public boolean areContentsTheSame(QIrcUser oldItem, QIrcUser newItem) {
+            return oldItem == newItem;
+        }
+
+        @Override
+        public boolean areItemsTheSame(QIrcUser item1, QIrcUser item2) {
+            return Objects.equals(item1.hostmask(), item2.hostmask());
+        }
+    });
+
+    public NickListWrapper(Drawer drawerRight, QIrcChannel channel) {
+        drawerRight.removeAllItems();
+        this.channel = channel;
+        this.list.addAll(channel.users());
+        this.list.addCallback(new UICallback() {
+            @Override
+            public void notifyItemInserted(int position) {
+                drawerRight.getItemAdapter().add(position, fromUser(list.get(position)));
+            }
+
+            @Override
+            public void notifyItemChanged(int position) {
+                drawerRight.getItemAdapter().notifyItemChanged(position);
+            }
+
+            @Override
+            public void notifyItemRemoved(int position) {
+                drawerRight.removeItemByPosition(position);
+            }
+
+            @Override
+            public void notifyItemMoved(int from, int to) {
+                notifyItemRemoved(from);
+                notifyItemInserted(from);
+            }
+
+            @Override
+            public void notifyItemRangeInserted(int position, int count) {
+                for (int i = position; i < position + count; i++) {
+                    notifyItemInserted(i);
+                }
+            }
+
+            @Override
+            public void notifyItemRangeChanged(int position, int count) {
+                for (int i = position; i < position + count; i++) {
+                    notifyItemChanged(i);
+                }
+            }
+
+            @Override
+            public void notifyItemRangeRemoved(int position, int count) {
+                for (int i = position; i < position + count; i++) {
+                    notifyItemRemoved(i);
+                }
+            }
+        });
+        for (QIrcUser user : list) {
+            if (user != null)
+                drawerRight.getItemAdapter().add(fromUser(user));
+        }
+    }
+
+    private IDrawerItem fromUser(QIrcUser user) {
+        return new PrimaryDrawerItem()
+                .withName(user.nick())
+                .withBadge(channel.network().modeToPrefix(channel.userModes(user)))
+                .withBadgeStyle(new BadgeStyle().withColor(0xFFFF0000).withTextColor(0xFFFFFFFF));
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferItem.java
index d2882f7a3796f6fbca813ac0d3bc4e73d8f04bb3..6fa5b285f444f45c2620bff4540999ca85c65500 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferItem.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferItem.java
@@ -123,7 +123,7 @@ public class BufferItem extends SecondaryDrawerItem {
     @Override
     public ColorHolder getTextColor() {
         int type = context.client().bufferSyncer().activity(buffer.getInfo().id());
-        if ((type & Message.Type.Plain.value | type & Message.Type.Notice.value) != 0)
+        if ((type & Message.Type.Plain.value) != 0  || (type & Message.Type.Notice.value) != 0)
             return ColorHolder.fromColor(context.themeUtil().res.colorTintMessage);
         else if ((type & ~Message.Type.DayChange.value) != 0)
             return ColorHolder.fromColor(context.themeUtil().res.colorTintActivity);
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 6192802965b6d716e184a60e5124f3f0e1487f98..b4ea95b7f65c7a37f0d1aa333f2f9db8b065cdc4 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
@@ -109,7 +109,7 @@ public class NetworkItem extends PrimaryDrawerItem implements IObservable<Drawer
 
     @Override
     public int compareTo(@NonNull NetworkItem another) {
-        return network.networkName().compareTo(another.network.networkName());
+        return network.networkName().compareToIgnoreCase(another.network.networkName());
     }
 
     public QNetwork getNetwork() {
diff --git a/app/src/main/java/de/kuschku/util/CompatibilityUtils.java b/app/src/main/java/de/kuschku/util/CompatibilityUtils.java
index ab0523c1e29a7e666e1495e45b328c173e37e84c..ec83d84b1cf5051af32ba0131c35d8f61c920875 100644
--- a/app/src/main/java/de/kuschku/util/CompatibilityUtils.java
+++ b/app/src/main/java/de/kuschku/util/CompatibilityUtils.java
@@ -106,4 +106,17 @@ public class CompatibilityUtils {
         }
         return defaultValue;
     }
+
+    /**
+     * Because Android’s String::split is broken
+     * @param str The string to be broken into chars
+     * @return A list with all substrings of length 1 of the first string, in order
+     */
+    public static String[] partStringByChar(String str) {
+        String[] chars = new String[str.length()];
+        for (int i = 0; i < chars.length; i++) {
+            chars[i] = str.substring(i, i+1);
+        }
+        return chars;
+    }
 }
diff --git a/app/src/main/java/de/kuschku/util/irc/ModeUtils.java b/app/src/main/java/de/kuschku/util/irc/ModeUtils.java
index 87fa50827f118bc22ae2515280a74e91592ee13e..048ee6f5d5ae3e56a34db7bab0f986f15a00f64b 100644
--- a/app/src/main/java/de/kuschku/util/irc/ModeUtils.java
+++ b/app/src/main/java/de/kuschku/util/irc/ModeUtils.java
@@ -27,13 +27,15 @@ import android.support.annotation.Nullable;
 import java.util.HashSet;
 import java.util.Set;
 
+import de.kuschku.util.CompatibilityUtils;
+
 public class ModeUtils {
     @NonNull
     public static Set<Character> toModes(@Nullable String modes) {
         Set<Character> modeSet = new HashSet<>();
         if (modes == null)
             return modeSet;
-        for (String mode : modes.split("")) {
+        for (String mode : CompatibilityUtils.partStringByChar(modes)) {
             if (mode.length() == 1)
                 modeSet.add(toMode(mode));
         }
diff --git a/app/src/main/java/de/kuschku/util/observables/lists/ObservableSet.java b/app/src/main/java/de/kuschku/util/observables/lists/ObservableSet.java
index 0f7b99e57d4d933ac2146294aa96806155568639..e67bbeb226f7a769b5fb5aea3ab87c4ef7334c89 100644
--- a/app/src/main/java/de/kuschku/util/observables/lists/ObservableSet.java
+++ b/app/src/main/java/de/kuschku/util/observables/lists/ObservableSet.java
@@ -33,7 +33,7 @@ import de.kuschku.util.observables.callbacks.wrappers.MultiElementCallbackWrappe
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
 @SuppressWarnings("unchecked")
-public class ObservableSet<T> extends HashSet<T> implements IObservableSet<ElementCallback<T>, T> {
+public class ObservableSet<T> extends HashSet<T> implements IObservableSet<ElementCallback<T>, T>, ElementCallback<T> {
     @NonNull
     private final MultiElementCallbackWrapper<T> callback = MultiElementCallbackWrapper.<T>of();
 
@@ -105,6 +105,21 @@ public class ObservableSet<T> extends HashSet<T> implements IObservableSet<Eleme
         return new CallbackedArrayListIterator<>(super.iterator());
     }
 
+    @Override
+    public void notifyItemInserted(T element) {
+        callback.notifyItemInserted(element);
+    }
+
+    @Override
+    public void notifyItemRemoved(T element) {
+        callback.notifyItemRemoved(element);
+    }
+
+    @Override
+    public void notifyItemChanged(T element) {
+        callback.notifyItemChanged(element);
+    }
+
     class CallbackedArrayListIterator<E> implements Iterator<E> {
         final Iterator<E> iterator;
         E current;