diff --git a/.gitmodules b/.gitmodules
index fb66a1d89c5dd2cdcb6b54df72c40882f0f3ff2d..5d4529c102bae6705be6292c8a1425ebb2932645 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
 [submodule "AndroidSlidingUpPanel"]
 	path = AndroidSlidingUpPanel
 	url = https://github.com/justjanne/AndroidSlidingUpPanel
-[submodule "aspm"]
-	path = aspm
-	url = https://github.com/justjanne/aspm
diff --git a/app/build.gradle b/app/build.gradle
index 326276be94914deb501712eefbef16d2f18668f6..dc2a506526a2b67124ded6d192678f11284e7ee6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -153,12 +153,9 @@ dependencies {
     compile 'com.android.support:design:23.1.1'
     compile 'com.android.support:support-v4:23.1.1'
     compile 'com.android.support:recyclerview-v7:23.1.1'
+    compile 'com.android.support:preference-v14:23.1.1'
     compile 'com.android.support:cardview-v7:23.1.1'
 
-    // Setting autobinding
-    compile(name:'annotations', ext:'jar')
-    apt(name:'compiler-all', ext:'jar')
-
     // UI autobinding
     compile 'com.jakewharton:butterknife:8.0.0-SNAPSHOT'
     apt 'com.jakewharton:butterknife-compiler:8.0.0-SNAPSHOT'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 81f3e83991ebf02234a322ed2b3ae4986538cbdb..32df2367fd107322107696e480db1fb3cce910be 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -32,10 +32,11 @@
         android:icon="@mipmap/ic_launcher"
         android:label="@string/appName"
         android:supportsRtl="true">
+
         <service android:name=".service.QuasselService" />
 
         <activity
-            android:name=".ui.chat.ChatActivity"
+            android:name=".ui.LoginActivity"
             android:label="@string/appName"
             android:launchMode="singleTask"
             android:theme="@style/AppTheme.Light">
@@ -45,6 +46,24 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity
+            android:name=".ui.chat.MainActivity"
+            android:label="@string/appName"
+            android:launchMode="singleTask"
+            android:theme="@style/AppTheme.Light" />
+
+        <activity
+            android:name=".ui.setup.AccountSetupActivity"
+            android:label="Setup a new Account"
+            android:launchMode="singleTask"
+            android:theme="@style/SetupTheme" />
+
+        <activity
+            android:name=".ui.setup.AccountSelectActivity"
+            android:label="Select an Account"
+            android:launchMode="singleTask"
+            android:theme="@style/SetupTheme" />
     </application>
 
 </manifest>
diff --git a/app/src/main/java/de/kuschku/libquassel/BusProvider.java b/app/src/main/java/de/kuschku/libquassel/BusProvider.java
index 61069b8d39db4cf89e7a161e71b939c579014a8a..47fc9be9e54441440487f6c4482df8ef6b32cd68 100644
--- a/app/src/main/java/de/kuschku/libquassel/BusProvider.java
+++ b/app/src/main/java/de/kuschku/libquassel/BusProvider.java
@@ -28,6 +28,7 @@ import java.util.UUID;
 
 import de.greenrobot.event.EventBus;
 import de.greenrobot.event.NoSubscriberEvent;
+import de.kuschku.libquassel.events.GeneralErrorEvent;
 
 public class BusProvider {
     @NonNull
@@ -83,6 +84,10 @@ public class BusProvider {
             this.identifier = identifier;
         }
 
+        public void onEvent(GeneralErrorEvent event) {
+            Log.e(identifier, event.getClass().getSimpleName(), event.exception);
+        }
+
         public void onEvent(NoSubscriberEvent event) {
             Log.e(identifier, String.valueOf(event));
         }
diff --git a/app/src/main/java/de/kuschku/libquassel/client/BufferManager.java b/app/src/main/java/de/kuschku/libquassel/client/BufferManager.java
index c6026667c27094b190ca1b9623029fc5f3a1df69..328dc8531c8370a4f3d544611f19ab8f1bcdd608 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/BufferManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/BufferManager.java
@@ -25,6 +25,8 @@ import android.support.annotation.IntRange;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import com.google.common.collect.Sets;
+
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
diff --git a/app/src/main/java/de/kuschku/libquassel/client/Client.java b/app/src/main/java/de/kuschku/libquassel/client/Client.java
index 1b3597e9b49c7a204697dd2b528399d1482c45ad..21104c93b9470e5be9dd5e3d9bcc5a6bd60d2971 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/Client.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/Client.java
@@ -200,7 +200,7 @@ public class Client extends AClient {
         } else if (connectionStatus == ConnectionChangeEvent.Status.CONNECTED) {
             // FIXME: Init buffer activity state and highlightss
         }
-        provider.sendEvent(new ConnectionChangeEvent(connectionStatus));
+        provider.event.postSticky(new ConnectionChangeEvent(connectionStatus));
     }
 
     @Nullable
@@ -318,6 +318,9 @@ public class Client extends AClient {
         requestInitObject("IgnoreListManager", "");
         //sendInitRequest("TransferManager", "");
         // This thing never gets sent...
+
+        assertNotNull(provider);
+        provider.event.postSticky(new InitEvent(initRequestMax - initRequests.size(), initRequestMax));
     }
 
     @NonNull
@@ -349,16 +352,16 @@ public class Client extends AClient {
     public void initObject(String className, @NonNull String objectName, @NonNull SyncableObject object) {
         assertNotNull(provider);
 
+        object.init(objectName, provider, this);
+
         if (connectionStatus() == ConnectionChangeEvent.Status.INITIALIZING_DATA) {
             initRequests.remove(hashName(className, objectName));
-            provider.sendEvent(new InitEvent(initRequestMax - initRequests.size(), initRequestMax));
+            provider.event.postSticky(new InitEvent(initRequestMax - initRequests.size(), initRequestMax));
             if (initRequests.isEmpty()) {
                 setConnectionStatus(ConnectionChangeEvent.Status.LOADING_BACKLOG);
             }
         }
 
-        object.init(objectName, provider, this);
-
         // Execute cached sync requests
         if (bufferedSyncs.size() > 0) {
             String key = hashName(className, objectName);
diff --git a/app/src/main/java/de/kuschku/libquassel/events/BufferChangeEvent.java b/app/src/main/java/de/kuschku/libquassel/events/BufferChangeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..2cef25718845eec5128c70e091b5232648ce9511
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/events/BufferChangeEvent.java
@@ -0,0 +1,25 @@
+/*
+ * 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.libquassel.events;
+
+public class BufferChangeEvent {
+}
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 f64af79214bd1e22e4b78750feb217f3483eb448..4fa6f80d735634b58205afeec33e896a5b64cbb0 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
@@ -33,6 +33,7 @@ import de.kuschku.libquassel.BusProvider;
 import de.kuschku.libquassel.client.Client;
 import de.kuschku.libquassel.events.BacklogInitEvent;
 import de.kuschku.libquassel.events.BacklogReceivedEvent;
+import de.kuschku.libquassel.events.BufferChangeEvent;
 import de.kuschku.libquassel.events.ConnectionChangeEvent;
 import de.kuschku.libquassel.localtypes.BacklogFilter;
 import de.kuschku.libquassel.localtypes.backlogstorage.BacklogStorage;
@@ -106,7 +107,7 @@ public class BacklogManager extends ABacklogManager<BacklogManager> {
         assertNotNull(provider);
 
         if (client.connectionStatus() == ConnectionChangeEvent.Status.LOADING_BACKLOG) {
-            provider.sendEvent(new BacklogInitEvent(waitingMax - waiting.size(), waitingMax));
+            provider.event.postSticky(new BacklogInitEvent(waitingMax - waiting.size(), waitingMax));
             if (waiting.isEmpty()) {
                 client.setConnectionStatus(ConnectionChangeEvent.Status.CONNECTED);
             }
@@ -157,9 +158,17 @@ public class BacklogManager extends ABacklogManager<BacklogManager> {
 
     @Override
     public void open(int bufferId) {
+        assertNotNull(provider);
+
         openBuffer = bufferId;
         if (bufferId != -1)
             client.bufferSyncer().requestMarkBufferAsRead(bufferId);
+        provider.sendEvent(new BufferChangeEvent());
+    }
+
+    @Override
+    public int open() {
+        return openBuffer;
     }
 
     @Override
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 14414e07205974fb8dfe1590638e1428e8061754..962f1c4f35b6735f60452378f2d3c0be97601f1f 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
@@ -163,7 +163,6 @@ public class BufferSyncer extends ABufferSyncer<BufferSyncer> {
         int lastMessage = client.backlogStorage().getLatest(buffer);
         if (lastMessage != -1) {
             requestSetLastSeenMsg(buffer, lastMessage);
-            requestSetMarkerLine(buffer, lastMessage);
         }
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
index 5cf65c0a3c1d08939a616734d2ecb4de451208a7..0fee0b05e725ccd5e9b6ef623988229e469c4a2f 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
@@ -41,7 +41,7 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> {
     @NonNull
     private final ObservableList<Integer> buffers;
     @NonNull
-    private final ObservableSet<Integer> buffersIds;
+    private final ObservableSet<Integer> bufferIds;
     @NonNull
     private final ObservableSet<Integer> removedBuffers;
     @NonNull
@@ -62,8 +62,10 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> {
         this.temporarilyRemovedBuffers = new ObservableSet<>(temporarilyRemovedBuffers);
         this.hideInactiveNetworks = hideInactiveNetworks;
         this.buffers = new ObservableList<>(buffers);
-        this.buffersIds = new ObservableSet<>();
-        bufferIds().addAll(buffers);
+        buffers.removeAll(removedBuffers);
+        buffers.removeAll(temporarilyRemovedBuffers);
+        this.bufferIds = new ObservableSet<>();
+        bufferIds.addAll(buffers);
         this.allowedBufferTypes = allowedBufferTypes;
         this.sortAlphabetically = sortAlphabetically;
         this.disableDecoration = disableDecoration;
@@ -212,7 +214,7 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> {
     @NonNull
     @Override
     public ObservableSet<Integer> bufferIds() {
-        return buffersIds;
+        return bufferIds;
     }
 
     @NonNull
@@ -355,8 +357,8 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> {
         this.hideInactiveNetworks = from.hideInactiveNetworks;
         this.buffers.clear();
         this.buffers.addAll(from.buffers);
-        this.buffersIds.retainAll(from.buffersIds);
-        this.buffersIds.addAll(from.buffersIds);
+        this.bufferIds.retainAll(from.bufferIds);
+        this.bufferIds.addAll(from.bufferIds);
         this.removedBuffers.retainAll(from.removedBuffers);
         this.removedBuffers.addAll(from.removedBuffers);
         this.temporarilyRemovedBuffers.retainAll(from.temporarilyRemovedBuffers);
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 d4d4f4864279634467cc6db46fb143b33f5cb208..b5904855f8b3952dbc97e2cb9a765d3c9014cbcf 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
@@ -66,6 +66,7 @@ public interface QBacklogManager<T extends QSyncableObject<T>> extends QSyncable
     ObservableComparableSortedList<Message> filtered(int id);
 
     void open(int bufferId);
+    int open();
 
     void receiveBacklog(Message msg);
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java b/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java
index d01c2b702825ccfa443f7fb6d0eb250af3749d44..3c31c7f8394fc401e4ae4006332ffd3cd6985637 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java
@@ -31,8 +31,12 @@ import de.kuschku.libquassel.QuasselClient;
 import de.kuschku.libquassel.client.ClientData;
 import de.kuschku.libquassel.client.FeatureFlags;
 import de.kuschku.libquassel.events.GeneralErrorEvent;
+import de.kuschku.libquassel.events.LoginRequireEvent;
 import de.kuschku.libquassel.localtypes.backlogstorage.MemoryBacklogStorage;
 import de.kuschku.libquassel.protocols.RemotePeer;
+import de.kuschku.quasseldroid_ng.ui.chat.Settings;
+import de.kuschku.quasseldroid_ng.util.accounts.Account;
+import de.kuschku.quasseldroid_ng.util.accounts.AccountManager;
 import de.kuschku.util.CompatibilityUtils;
 import de.kuschku.util.ServerAddress;
 import de.kuschku.util.certificates.SQLiteCertificateManager;
@@ -49,6 +53,9 @@ public class ClientBackgroundThread implements Runnable {
     @NonNull
     private final QuasselClient client;
 
+    private final Settings settings;
+    private final AccountManager manager;
+
     public ClientBackgroundThread(@NonNull BusProvider provider, @NonNull ServerAddress address, @NonNull Context context) {
         this.client = new QuasselClient(
                 provider,
@@ -57,6 +64,10 @@ public class ClientBackgroundThread implements Runnable {
                 new MemoryBacklogStorage()
         );
         this.client.connect(address);
+        this.client.provider.event.registerSticky(this);
+
+        settings = new Settings(context);
+        manager = new AccountManager(context);
     }
 
     @NonNull
@@ -76,4 +87,11 @@ public class ClientBackgroundThread implements Runnable {
     public void close() {
         client.disconnect();
     }
+
+    public void onEvent(LoginRequireEvent event) {
+        if (!event.failedLast) {
+            Account account = manager.account(settings.lastAccount.get());
+            client().client.login(account.user, account.pass);
+        }
+    }
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.java b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.java
index d94c617f56dd6163739757e9e5571ae8fcc0dec9..8a75f4385d911b00da17b8f21a0e820c5b0e0419 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.java
@@ -28,8 +28,12 @@ import android.os.IBinder;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import java.util.HashSet;
+import java.util.Set;
+
 import de.kuschku.libquassel.BusProvider;
 import de.kuschku.util.ServerAddress;
+import de.kuschku.util.backports.Consumer;
 
 public class QuasselService extends Service {
     @NonNull
@@ -38,6 +42,8 @@ public class QuasselService extends Service {
     @Nullable
     private ClientBackgroundThread bgThread;
 
+    private Set<Consumer<ClientBackgroundThread>> consumers = new HashSet<>();
+
     @Override
     public IBinder onBind(Intent intent) {
         return binder;
@@ -52,6 +58,7 @@ public class QuasselService extends Service {
         public void startBackgroundThread(@NonNull BusProvider provider, @NonNull ServerAddress address) {
             bgThread = new ClientBackgroundThread(provider, address, QuasselService.this);
             new Thread(bgThread).start();
+            notify(bgThread);
         }
 
         @Nullable
@@ -62,6 +69,19 @@ public class QuasselService extends Service {
         public void stopBackgroundThread() {
             if (bgThread != null) bgThread.close();
             bgThread = null;
+            notify(bgThread);
+        }
+
+        public void addCallback(Consumer<ClientBackgroundThread> consumer) {
+            consumers.add(consumer);
+        }
+        public void removeCallback(Consumer<ClientBackgroundThread> consumer) {
+            consumers.remove(consumer);
+        }
+        private void notify(ClientBackgroundThread thread) {
+            for (Consumer<ClientBackgroundThread> consumer : consumers) {
+                consumer.apply(thread);
+            }
         }
     }
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/LoginActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/LoginActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..c690cd62b2d6da8ebc03e034bf35340b049b477e
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/LoginActivity.java
@@ -0,0 +1,82 @@
+/*
+ * 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;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+
+import de.kuschku.quasseldroid_ng.ui.chat.MainActivity;
+import de.kuschku.quasseldroid_ng.ui.chat.Settings;
+import de.kuschku.quasseldroid_ng.ui.chat.util.ServiceHelper;
+import de.kuschku.quasseldroid_ng.ui.setup.AccountSelectActivity;
+import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+
+public class LoginActivity extends AppCompatActivity {
+    private AppContext context = new AppContext();
+
+    private boolean firstStart = true;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        ServiceHelper.initTheme(context, this);
+        context.withSettings(new Settings(this));
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (!checkReady()) {
+            finish();
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (resultCode == RESULT_OK) {
+            context.settings().lastAccount.set(data.getBundleExtra("extra").getString("account"));
+            checkReady();
+            firstStart = true;
+        } else if (context.settings().lastAccount.get().isEmpty()) {
+            finish();
+        }
+    }
+
+    private boolean checkReady() {
+        if (context.settings().lastAccount.get().isEmpty()) {
+            Intent intent = new Intent(this, AccountSelectActivity.class);
+            startActivityForResult(intent, 0);
+            firstStart = true;
+            return true;
+        } else if (firstStart) {
+            startActivity(new Intent(this, MainActivity.class));
+            firstStart = false;
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
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
deleted file mode 100644
index 65af818a6dd6e87893f101fc821929b51250ca09..0000000000000000000000000000000000000000
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java
+++ /dev/null
@@ -1,902 +0,0 @@
-/*
- * 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 android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.support.annotation.IntRange;
-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.widget.SwipeRefreshLayout;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.ActionMenuView;
-import android.support.v7.widget.AppCompatEditText;
-import android.support.v7.widget.AppCompatImageButton;
-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.util.Log;
-import android.view.Gravity;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ScrollView;
-
-import com.afollestad.materialdialogs.MaterialDialog;
-import com.google.common.base.Splitter;
-import com.mikepenz.fastadapter.FastAdapter;
-import com.mikepenz.fastadapter.IExpandable;
-import com.mikepenz.fastadapter.IItem;
-import com.mikepenz.fastadapter.adapters.ItemAdapter;
-import com.mikepenz.materialdrawer.AccountHeader;
-import com.mikepenz.materialdrawer.AccountHeaderBuilder;
-import com.mikepenz.materialdrawer.Drawer;
-import com.mikepenz.materialdrawer.DrawerBuilder;
-import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
-import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
-import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
-import com.sothree.slidinguppanel.SlidingUpPanelLayout;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import aspm.annotations.BooleanPreference;
-import aspm.annotations.IntPreference;
-import aspm.annotations.PreferenceWrapper;
-import aspm.annotations.StringPreference;
-import butterknife.Bind;
-import butterknife.ButterKnife;
-import de.kuschku.libquassel.BusProvider;
-import de.kuschku.libquassel.client.Client;
-import de.kuschku.libquassel.events.BacklogInitEvent;
-import de.kuschku.libquassel.events.BacklogReceivedEvent;
-import de.kuschku.libquassel.events.ConnectionChangeEvent;
-import de.kuschku.libquassel.events.GeneralErrorEvent;
-import de.kuschku.libquassel.events.InitEvent;
-import de.kuschku.libquassel.events.LagChangedEvent;
-import de.kuschku.libquassel.events.LoginRequireEvent;
-import de.kuschku.libquassel.events.UnknownCertificateEvent;
-import de.kuschku.libquassel.localtypes.BacklogFilter;
-import de.kuschku.libquassel.localtypes.buffers.Buffer;
-import de.kuschku.libquassel.localtypes.buffers.ChannelBuffer;
-import de.kuschku.libquassel.message.Message;
-import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager;
-import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
-import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
-import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
-import de.kuschku.quasseldroid_ng.BuildConfig;
-import de.kuschku.quasseldroid_ng.R;
-import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread;
-import de.kuschku.quasseldroid_ng.service.QuasselService;
-import de.kuschku.quasseldroid_ng.ui.chat.chatview.MessageAdapter;
-import de.kuschku.quasseldroid_ng.ui.chat.drawer.BufferItem;
-import de.kuschku.quasseldroid_ng.ui.chat.drawer.BufferViewConfigItem;
-import de.kuschku.quasseldroid_ng.ui.editor.AdvancedEditor;
-import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
-import de.kuschku.quasseldroid_ng.ui.theme.AppTheme;
-import de.kuschku.quasseldroid_ng.ui.theme.ThemeUtil;
-import de.kuschku.util.ServerAddress;
-import de.kuschku.util.certificates.CertificateUtils;
-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 static de.kuschku.util.AndroidAssert.assertNotNull;
-
-@UiThread
-public class ChatActivity extends AppCompatActivity {
-    @NonNull
-    private final Status status = new Status();
-    @NonNull
-    private final ServiceInterface serviceInterface = new ServiceInterface();
-    @NonNull
-    private final AppContext context = new AppContext();
-    // Main layout
-    @Bind(R.id.toolbar)
-    Toolbar toolbar;
-    @Bind(R.id.sliding_layout)
-    SlidingUpPanelLayout slidingLayout;
-    // Input Line
-    @Bind(R.id.chatline_scroller)
-    ScrollView chatlineScroller;
-    @Bind(R.id.chatline)
-    AppCompatEditText chatline;
-    @Bind(R.id.send)
-    AppCompatImageButton send;
-    // Input History
-    @Bind(R.id.sliding_layout_history)
-    SlidingUpPanelLayout slidingLayoutHistory;
-    @Bind(R.id.msg_history)
-    RecyclerView msgHistory;
-    // Advanced Formatter
-    @Bind(R.id.formatting_menu)
-    ActionMenuView formattingMenu;
-    @Bind(R.id.formatting_toolbar)
-    Toolbar formattingToolbar;
-    // Content view
-    @Bind(R.id.swipe_view)
-    SwipeRefreshLayout swipeView;
-    @Bind(R.id.messages)
-    RecyclerView messages;
-    private MessageAdapter messageAdapter;
-    private AccountHeader accountHeader;
-    private Drawer drawerLeft;
-    private Drawer drawerRight;
-    private AdvancedEditor editor;
-    @Nullable
-    private QuasselService.LocalBinder binder;
-    @Nullable
-    private final ServiceConnection serviceConnection = new ServiceConnection() {
-        @UiThread
-        public void onServiceConnected(ComponentName cn, IBinder service) {
-            assertNotNull(cn);
-            assertNotNull(service);
-
-            if (service instanceof QuasselService.LocalBinder) {
-                ChatActivity.this.binder = (QuasselService.LocalBinder) service;
-                if (binder != null && binder.getBackgroundThread() != null) {
-                    ClientBackgroundThread backgroundThread = binder.getBackgroundThread();
-                    assertNotNull(backgroundThread);
-
-                    serviceInterface.disconnect();
-
-                    BusProvider provider = backgroundThread.client().provider;
-                    Client client = backgroundThread.client().client;
-                    context.setProvider(provider);
-                    context.setClient(client);
-                    provider.event.register(ChatActivity.this);
-
-
-                    updateSubTitle();
-                    if (client.connectionStatus() == ConnectionChangeEvent.Status.CONNECTED) {
-                        updateBufferViewConfigs();
-                    }
-                }
-            }
-        }
-
-        @UiThread
-        public void onServiceDisconnected(ComponentName cn) {
-            assertNotNull(cn);
-
-            serviceInterface.disconnect();
-            binder = null;
-        }
-    };
-
-    private static void updateNoColor(@Nullable Buffer buffer, @NonNull Menu menu) {
-        boolean isNoColor = isNoColor(buffer);
-        MenuItem item_bold = menu.findItem(R.id.format_bold);
-        if (item_bold != null)
-            item_bold.setEnabled(!isNoColor);
-        MenuItem item_italic = menu.findItem(R.id.format_italic);
-        if (item_italic != null)
-            item_italic.setEnabled(!isNoColor);
-        MenuItem item_underline = menu.findItem(R.id.format_underline);
-        if (item_underline != null)
-            item_underline.setEnabled(!isNoColor);
-        MenuItem item_paint = menu.findItem(R.id.format_paint);
-        if (item_paint != null)
-            item_paint.setEnabled(!isNoColor);
-        MenuItem item_fill = menu.findItem(R.id.format_fill);
-        if (item_fill != null)
-            item_fill.setEnabled(!isNoColor);
-    }
-
-    public static boolean isNoColor(@Nullable Buffer buffer) {
-        if (buffer == null)
-            return false;
-        if (!(buffer instanceof ChannelBuffer))
-            return false;
-        QIrcChannel channel = ((ChannelBuffer) buffer).getChannel();
-        return channel != null && channel.hasMode('c');
-    }
-
-    private void updateSubTitle() {
-        Client client = context.client();
-        if (client != null) {
-            ConnectionChangeEvent.Status status = client.connectionStatus();
-            if (status == ConnectionChangeEvent.Status.CONNECTED) {
-                if (this.status.bufferId > 0) {
-                    Buffer buffer = client.bufferManager().buffer(this.status.bufferId);
-                    if (buffer != null && buffer instanceof ChannelBuffer) {
-                        QIrcChannel channel = ((ChannelBuffer) buffer).getChannel();
-                        if (channel != null) {
-                            updateSubTitle(channel.topic());
-                            return;
-                        }
-                    }
-                }
-            } else if (status != null) {
-                updateSubTitle(status.name());
-                return;
-            }
-        }
-        updateSubTitle("");
-    }
-
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        setupContext();
-
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_chat);
-        ButterKnife.bind(this);
-        setSupportActionBar(toolbar);
-
-        Intent intent = new Intent(this, QuasselService.class);
-        startService(intent);
-
-        setupHeader(savedInstanceState);
-
-        setupDrawer(savedInstanceState);
-
-        setupEditor();
-
-        setupContent();
-
-        setupHistory();
-
-        initLoader();
-    }
-
-    @Override
-    protected void onPause() {
-        serviceInterface.disconnect();
-        unbindService(serviceConnection);
-        super.onPause();
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        Intent intent = new Intent(this, QuasselService.class);
-        bindService(intent, serviceConnection, Context.BIND_IMPORTANT);
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-    }
-
-    @Override
-    protected void onRestart() {
-        super.onRestart();
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-    }
-
-    @Override
-    protected void onNewIntent(Intent intent) {
-        super.onNewIntent(intent);
-    }
-
-    @Override
-    protected void onSaveInstanceState(@NonNull Bundle outState) {
-        assertNotNull(outState);
-
-        super.onSaveInstanceState(outState);
-        status.onSaveInstanceState(outState);
-    }
-
-    @Override
-    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
-        assertNotNull(savedInstanceState);
-
-        super.onRestoreInstanceState(savedInstanceState);
-        status.onRestoreInstanceState(savedInstanceState);
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.chat, menu);
-        return super.onCreateOptionsMenu(menu);
-    }
-
-    // FIXME: REWRITE
-    @Override
-    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
-        assertNotNull(item);
-
-        List<Integer> filterSettings = Arrays.asList(
-                Message.Type.Join.value,
-                Message.Type.Part.value,
-                Message.Type.Quit.value,
-                Message.Type.Nick.value,
-                Message.Type.Mode.value,
-                Message.Type.Topic.value
-        );
-        int[] filterSettingsInts = new int[filterSettings.size()];
-        for (int i = 0; i < filterSettingsInts.length; i++) {
-            filterSettingsInts[i] = filterSettings.get(i);
-        }
-
-        switch (item.getItemId()) {
-            case R.id.action_hide_events: {
-                if (context.client() != null) {
-                    BacklogFilter backlogFilter = context.client().backlogManager().filter(status.bufferId);
-                    if (backlogFilter != null) {
-                        int oldFilters = backlogFilter.getFilters();
-                        List<Integer> oldFiltersList = new ArrayList<>();
-                        for (int type : filterSettings) {
-                            if ((type & oldFilters) != 0)
-                                oldFiltersList.add(filterSettings.indexOf(type));
-                        }
-                        Integer[] selectedIndices = oldFiltersList.toArray(new Integer[oldFiltersList.size()]);
-                        new MaterialDialog.Builder(this)
-                                .items(
-                                        "Joins",
-                                        "Parts",
-                                        "Quits",
-                                        "Nick Changes",
-                                        "Mode Changes",
-                                        "Topic Changes"
-                                )
-                                .itemsIds(filterSettingsInts)
-                                .itemsCallbackMultiChoice(
-                                        selectedIndices,
-                                        (dialog, which, text) -> false
-                                )
-                                .positiveText("Select")
-                                .negativeText("Cancel")
-                                .onPositive((dialog, which) -> {
-                                    int filters = 0x00000000;
-                                    if (dialog.getSelectedIndices() != null)
-                                        for (int i : dialog.getSelectedIndices()) {
-                                            filters |= filterSettings.get(i);
-                                        }
-                                    backlogFilter.setFilters(filters);
-                                })
-                                .build()
-                                .show();
-                    }
-                }
-            }
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-    private void setupContext() {
-        WrappedSettings settings = new WrappedSettings(this);
-        context.setSettings(settings);
-        AppTheme theme = AppTheme.themeFromString(settings.theme.get());
-        setTheme(theme.themeId);
-        context.setThemeUtil(new ThemeUtil(this, theme));
-    }
-
-    private void setupEditorLayout() {
-        assertNotNull(slidingLayout);
-
-        slidingLayout.setAntiDragView(R.id.card_panel);
-        slidingLayout.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() {
-            @Override
-            public void onPanelSlide(View panel, float slideOffset) {
-
-            }
-
-            @Override
-            public void onPanelCollapsed(View panel) {
-                setChatlineExpanded(false);
-            }
-
-            @Override
-            public void onPanelExpanded(View panel) {
-                setChatlineExpanded(true);
-            }
-
-            @Override
-            public void onPanelAnchored(View panel) {
-
-            }
-
-            @Override
-            public void onPanelHidden(View panel) {
-
-            }
-        });
-        setChatlineExpanded(slidingLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED);
-    }
-
-    private void initLoader() {
-        assertNotNull(swipeView);
-        ThemeUtil themeUtil = context.themeUtil();
-        assertNotNull(themeUtil);
-
-
-        swipeView.setEnabled(false);
-        swipeView.setColorSchemeColors(themeUtil.res.colorPrimary);
-        swipeView.setOnRefreshListener(() -> {
-            Client client = context.client();
-            assertNotNull(client);
-            QBacklogManager<? extends QBacklogManager> backlogManager = client.backlogManager();
-            assertNotNull(backlogManager);
-            backlogManager.requestMoreBacklog(status.bufferId, 20);
-        });
-    }
-
-    private void setupHistory() {
-        assertNotNull(msgHistory);
-
-        FastAdapter<IItem> fastAdapter = new FastAdapter<>();
-        ItemAdapter<IItem> itemAdapter = new ItemAdapter<>();
-        itemAdapter.wrap(fastAdapter);
-        itemAdapter.add(
-                new PrimaryDrawerItem().withName("Entry #1"),
-                new PrimaryDrawerItem().withName("Entry #2"),
-                new PrimaryDrawerItem().withName("Entry #3"),
-                new PrimaryDrawerItem().withName("Entry #4"),
-                new PrimaryDrawerItem().withName("Entry #5"),
-                new PrimaryDrawerItem().withName("Entry #6"),
-                new PrimaryDrawerItem().withName("Entry #7"),
-                new PrimaryDrawerItem().withName("Entry #8"),
-                new PrimaryDrawerItem().withName("Entry #9"),
-                new PrimaryDrawerItem().withName("Entry #10"),
-                new PrimaryDrawerItem().withName("Entry #11"),
-                new PrimaryDrawerItem().withName("Entry #12"),
-                new PrimaryDrawerItem().withName("Entry #13"),
-                new PrimaryDrawerItem().withName("Entry #14"),
-                new PrimaryDrawerItem().withName("Entry #15"),
-                new PrimaryDrawerItem().withName("Entry #16")
-        );
-        msgHistory.setAdapter(fastAdapter);
-        msgHistory.setLayoutManager(new LinearLayoutManager(this));
-        msgHistory.setItemAnimator(new DefaultItemAnimator());
-    }
-
-    private void setupContent() {
-        assertNotNull(messages);
-
-        messages.setItemAnimator(new DefaultItemAnimator());
-        messages.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true));
-        messageAdapter = new MessageAdapter(this, context, new AutoScroller(messages));
-        messages.setAdapter(messageAdapter);
-    }
-
-    private void setupEditor() {
-        assertNotNull(formattingMenu);
-        assertNotNull(slidingLayoutHistory);
-        assertNotNull(send);
-        assertNotNull(chatline);
-
-        getMenuInflater().inflate(R.menu.formatting, formattingMenu.getMenu());
-        formattingMenu.setOnMenuItemClickListener(item -> {
-            switch (item.getItemId()) {
-                case R.id.format_bold:
-                    editor.toggleBold();
-                    return true;
-                case R.id.format_italic:
-                    editor.toggleItalic();
-                    return true;
-                case R.id.format_underline:
-                    editor.toggleUnderline();
-                    return true;
-                case R.id.action_history:
-                    slidingLayoutHistory.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
-                    return true;
-                default:
-                    return false;
-            }
-        });
-        editor = new AdvancedEditor(context, chatline);
-        send.setOnClickListener(view -> sendInput());
-
-        setupEditorLayout();
-    }
-
-    private void setupDrawer(@Nullable Bundle savedInstanceState) {
-        drawerLeft = new DrawerBuilder()
-                .withActivity(this)
-                .withToolbar(toolbar)
-                .withAccountHeader(accountHeader)
-                .withSavedInstance(savedInstanceState)
-                .withTranslucentStatusBar(true)
-                .build();
-        assertNotNull(drawerLeft);
-        assertNotNull(drawerLeft.getAdapter());
-        drawerLeft.addStickyFooterItem(new PrimaryDrawerItem().withIcon(R.drawable.ic_server_light).withName("(Re-)Connect").withIdentifier(-1));
-        drawerLeft.addStickyFooterItem(new SecondaryDrawerItem().withName("Settings").withIdentifier(-2));
-        drawerLeft.setOnDrawerItemClickListener((view, position, drawerItem) -> {
-            long identifier = drawerItem.getIdentifier();
-            if (identifier == -1) {
-                showConnectDialog();
-                return false;
-            } else if (identifier == -2) {
-                showThemeDialog();
-                return false;
-            } else {
-                if (((IExpandable) drawerItem).getSubItems() != null) {
-                    drawerLeft.getAdapter().toggleExpandable(position);
-                    return true;
-                } else if (drawerItem instanceof BufferItem) {
-                    selectBuffer(((BufferItem) drawerItem).getBuffer().getInfo().id());
-                    return false;
-                }
-                return true;
-            }
-        });
-        drawerRight = new DrawerBuilder()
-                .withActivity(this)
-                .withSavedInstance(savedInstanceState)
-                .withDrawerGravity(Gravity.END)
-                .build();
-    }
-
-    private void setupHeader(@Nullable Bundle savedInstanceState) {
-        accountHeader = new AccountHeaderBuilder()
-                .withActivity(this)
-                .withCompactStyle(true)
-                .withHeaderBackground(R.drawable.bg)
-                .withSavedInstance(savedInstanceState)
-                .withProfileImagesVisible(false)
-                .withOnAccountHeaderListener((view, profile, current) -> {
-                    selectBufferViewConfig((int) profile.getIdentifier());
-                    return true;
-                })
-                .build();
-    }
-
-    public void setChatlineExpanded(boolean expanded) {
-        assertNotNull(chatline);
-        assertNotNull(chatline.getLayoutParams());
-        ThemeUtil themeUtil = context.themeUtil();
-        assertNotNull(themeUtil);
-
-        int selectionStart = chatline.getSelectionStart();
-        int selectionEnd = chatline.getSelectionEnd();
-
-        if (expanded) {
-            chatline.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
-        } else {
-            chatline.getLayoutParams().height = themeUtil.res.actionBarSize;
-        }
-        chatline.setSingleLine(!expanded);
-
-        chatline.setSelection(selectionStart, selectionEnd);
-    }
-
-    // FIXME: Rewrite properly
-    public void showThemeDialog() {
-        String[] strings = new String[AppTheme.values().length];
-        int startIndex = -1;
-        for (int i = 0; i < strings.length; i++) {
-            AppTheme theme = AppTheme.values()[i];
-            strings[i] = theme.name();
-            if (theme.name().equals(context.settings().theme.get())) startIndex = i;
-        }
-
-        new MaterialDialog.Builder(this)
-                .items(strings)
-                .positiveText("Select Theme")
-                .negativeText("Cancel")
-                .itemsCallbackSingleChoice(startIndex, (dialog, itemView, which, text) -> {
-                    context.settings().theme.set(strings[dialog.getSelectedIndex()]);
-                    recreate();
-                    return true;
-                })
-                .negativeColor(context.themeUtil().res.colorForeground)
-                .build()
-                .show();
-    }
-
-    private void selectBufferViewConfig(@IntRange(from = -1) int bufferViewConfigId) {
-        assertNotNull(drawerLeft);
-        assertNotNull(accountHeader);
-        Client client = context.client();
-        assertNotNull(client);
-
-        status.bufferViewConfigId = bufferViewConfigId;
-        accountHeader.setActiveProfile(bufferViewConfigId, false);
-
-        if (bufferViewConfigId == -1) {
-            drawerLeft.removeAllItems();
-        } else {
-            drawerLeft.removeAllItems();
-            QBufferViewManager bufferViewManager = client.bufferViewManager();
-            assertNotNull(bufferViewManager);
-            QBufferViewConfig viewConfig = bufferViewManager.bufferViewConfig(bufferViewConfigId);
-            assertNotNull(viewConfig);
-
-            new BufferViewConfigItem(drawerLeft, viewConfig, context);
-        }
-    }
-
-    private void selectBuffer(@IntRange(from = -1) int bufferId) {
-        context.client().backlogManager().open(bufferId);
-        if (bufferId == -1) {
-            status.bufferId = bufferId;
-            swipeView.setEnabled(false);
-            context.client().backlogManager().open(bufferId);
-
-            messageAdapter.setMessageList(MessageAdapter.emptyList());
-            toolbar.setTitle(getResources().getString(R.string.appName));
-        } else {
-            status.bufferId = bufferId;
-            swipeView.setEnabled(true);
-            context.client().backlogManager().open(bufferId);
-
-            // Make sure we are actually connected
-            ObservableSortedList<Message> list = context.client().backlogManager().filtered(bufferId);
-            Buffer buffer = context.client().bufferManager().buffer(bufferId);
-            // Make sure everything is properly defined
-            assertNotNull("Buffer is null: " + bufferId, buffer);
-            assertNotNull(list);
-
-            messageAdapter.setMessageList(list);
-            toolbar.setTitle(buffer.getName());
-            updateNoColor(buffer, formattingMenu.getMenu());
-
-            if (buffer instanceof ChannelBuffer && ((ChannelBuffer) buffer).getChannel() != null) {
-                NickListWrapper nicklistwrapper = new NickListWrapper(drawerRight, ((ChannelBuffer) buffer).getChannel());
-            } else {
-                drawerRight.removeAllItems();
-            }
-        }
-        updateSubTitle();
-    }
-
-    private void onConnectionEstablished() {
-        assertNotNull(binder);
-        assertNotNull(binder.getBackgroundThread());
-        context.setClient(binder.getBackgroundThread().client().client);
-        assertNotNull(context.client());
-    }
-
-    private void sendInput() {
-        if (context.client() == null) return;
-
-        int bufferId = status.bufferId;
-
-        if (bufferId >= 0) {
-            Buffer buffer = context.client().bufferManager().buffer(bufferId);
-            assertNotNull(buffer);
-
-            String text = editor.toFormatString();
-            context.client().sendInput(buffer.getInfo(), text);
-            chatline.setText("");
-        } else {
-            Snackbar.make(messages, "No buffer opened", Snackbar.LENGTH_LONG).show();
-        }
-    }
-
-    public void onEventMainThread(@NonNull LoginRequireEvent event) {
-        assertNotNull(context.client());
-
-        if (event.failedLast)
-            showLoginDialog();
-        else
-            context.client().login(
-                    context.settings().lastUsername.or(""),
-                    context.settings().lastPassword.or("")
-            );
-    }
-
-    public void onEventMainThread(@NonNull ConnectionChangeEvent event) {
-        updateSubTitle();
-
-        switch (event.status) {
-            case CONNECTED:
-                updateBufferViewConfigs();
-                break;
-        }
-    }
-
-    public void onEventMainThread(@NonNull BacklogInitEvent event) {
-        updateSubTitle(event.toString());
-    }
-
-    public void onEventMainThread(@NonNull InitEvent event) {
-        updateSubTitle(event.toString());
-    }
-
-    private void updateBufferViewConfigs() {
-        assertNotNull(context.client().bufferViewManager());
-        List<QBufferViewConfig> bufferViews = context.client().bufferViewManager().bufferViewConfigs();
-        accountHeader.clear();
-        for (QBufferViewConfig viewConfig : bufferViews) {
-            if (viewConfig != null) {
-                accountHeader.addProfiles(
-                        new ProfileDrawerItem()
-                                .withName(viewConfig.bufferViewName())
-                                .withIdentifier(viewConfig.bufferViewId())
-                );
-            }
-        }
-        selectBufferViewConfig(status.bufferViewConfigId);
-        selectBuffer(status.bufferId);
-    }
-
-    private void showLoginDialog() {
-        MaterialDialog dialog = new MaterialDialog.Builder(this)
-                .title(R.string.labelLogin)
-                .customView(R.layout.dialog_login, false)
-                .onPositive((dialog1, which) -> {
-                    View parent = dialog1.getCustomView();
-                    assertNotNull(parent);
-                    AppCompatEditText usernameField = (AppCompatEditText) parent.findViewById(R.id.username);
-                    AppCompatEditText passwordField = (AppCompatEditText) parent.findViewById(R.id.password);
-                    String username = usernameField.getText().toString();
-                    String password = passwordField.getText().toString();
-                    context.settings().lastUsername.set(username);
-                    context.settings().lastPassword.set(password);
-                    context.client().login(username, password);
-                })
-                .cancelListener(dialog1 -> {
-                    if (binder != null)
-                        binder.stopBackgroundThread();
-                    serviceInterface.disconnect();
-                })
-                .negativeColor(context.themeUtil().res.colorForeground)
-                .positiveText(R.string.labelLogin)
-                .negativeText(R.string.labelCancel)
-                .build();
-        ((AppCompatEditText) dialog.getView().findViewById(R.id.username)).setText(context.settings().lastUsername.get());
-        ((AppCompatEditText) dialog.getView().findViewById(R.id.password)).setText(context.settings().lastPassword.get());
-        dialog.show();
-    }
-
-    public void showConnectDialog() {
-        MaterialDialog dialog = new MaterialDialog.Builder(this)
-                .title(R.string.labelAddress)
-                .customView(R.layout.dialog_address, false)
-                .onPositive((dialog1, which) -> {
-                    if (binder != null && binder.getBackgroundThread() != null)
-                        binder.stopBackgroundThread();
-
-                    View parent = dialog1.getCustomView();
-                    assertNotNull(parent);
-                    AppCompatEditText hostField = (AppCompatEditText) parent.findViewById(R.id.host);
-                    AppCompatEditText portField = (AppCompatEditText) parent.findViewById(R.id.port);
-                    String host = hostField.getText().toString().trim();
-                    int port = Integer.valueOf(portField.getText().toString().trim());
-                    context.settings().lastHost.set(host);
-                    context.settings().lastPort.set(port);
-                    serviceInterface.connect(new ServerAddress(host, port));
-                })
-                .negativeColor(context.themeUtil().res.colorForeground)
-                .positiveText(R.string.labelConnect)
-                .negativeText(R.string.labelCancel)
-                .build();
-        AppCompatEditText hostField = (AppCompatEditText) dialog.getView().findViewById(R.id.host);
-        AppCompatEditText portField = (AppCompatEditText) dialog.getView().findViewById(R.id.port);
-
-        hostField.setText(context.settings().lastHost.get());
-        portField.setText(String.valueOf(context.settings().lastPort.get()));
-
-        dialog.show();
-    }
-
-    public void onEventMainThread(@NonNull BacklogReceivedEvent event) {
-        if (event.bufferId == status.bufferId) {
-            swipeView.setRefreshing(false);
-        }
-    }
-
-    public void onEventMainThread(@NonNull UnknownCertificateEvent event) {
-        new MaterialDialog.Builder(this)
-                .content(context.themeUtil().translations.warningCertificate + "\n" + CertificateUtils.certificateToFingerprint(event.certificate, ""))
-                .title("Unknown Certificate")
-                .onPositive((dialog, which) -> {
-                    if (binder != null && binder.getBackgroundThread() != null) {
-                        binder.getBackgroundThread().client().certificateManager.addCertificate(event.certificate, event.address);
-                    }
-                })
-                .negativeColor(context.themeUtil().res.colorForeground)
-                .positiveText("Yes")
-                .negativeText("No")
-                .build()
-                .show();
-    }
-
-    public void onEventMainThread(@NonNull GeneralErrorEvent event) {
-        assertNotNull(messages);
-
-        Snackbar.make(messages, event.toString(), Snackbar.LENGTH_LONG).show();
-        for (String line : Splitter.fixedLength(2048).split(event.toString())) {
-            Log.e("ChatActivity", line);
-        }
-        if (event.exception != null)
-            event.exception.printStackTrace();
-    }
-
-    public void onEventMainThread(LagChangedEvent event) {
-        updateSubTitle();
-    }
-
-    private void updateSubTitle(@Nullable CharSequence text) {
-        assertNotNull(toolbar);
-
-        if (text != null) {
-            toolbar.setSubtitle(text);
-        } else {
-            toolbar.setSubtitle("");
-        }
-    }
-
-    private static class Status extends Storable {
-        @Store
-        int bufferId = -1;
-        @Store
-        int bufferViewConfigId = -1;
-    }
-
-    @PreferenceWrapper(BuildConfig.APPLICATION_ID)
-    public static abstract class Settings {
-        @StringPreference("QUASSEL_LIGHT")
-        String theme;
-        @BooleanPreference(false)
-        boolean fullHostmask;
-        @IntPreference(2)
-        int textSize;
-        @BooleanPreference(true)
-        boolean mircColors;
-
-        @StringPreference("")
-        String lastHost;
-        @IntPreference(4242)
-        int lastPort;
-        @StringPreference("")
-        String lastUsername;
-        @StringPreference("")
-        String lastPassword;
-    }
-
-    private class ServiceInterface {
-        private void connect(@NonNull ServerAddress address) {
-            assertNotNull(binder);
-            disconnect();
-
-            context.setProvider(new BusProvider());
-            context.provider().event.register(ChatActivity.this);
-            binder.startBackgroundThread(context.provider(), address);
-            onConnectionEstablished();
-        }
-
-        private void disconnect() {
-            if (context.provider() != null) {
-                context.provider().event.unregister(ChatActivity.this);
-            }
-            if (context.client() != null) {
-                context.client().backlogManager().open(-1);
-            }
-            context.setProvider(null);
-            context.setClient(null);
-        }
-    }
-}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..88bfaa70097c26629499854172bb93cd85fc0921
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java
@@ -0,0 +1,183 @@
+/*
+ * 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 android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.FrameLayout;
+
+import com.mikepenz.materialdrawer.AccountHeader;
+import com.mikepenz.materialdrawer.AccountHeaderBuilder;
+import com.mikepenz.materialdrawer.Drawer;
+
+import aspm.annotations.BooleanPreference;
+import aspm.annotations.IntPreference;
+import aspm.annotations.PreferenceWrapper;
+import aspm.annotations.StringPreference;
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.libquassel.events.ConnectionChangeEvent;
+import de.kuschku.libquassel.events.GeneralErrorEvent;
+import de.kuschku.quasseldroid_ng.BuildConfig;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread;
+import de.kuschku.quasseldroid_ng.util.BoundActivity;
+import de.kuschku.quasseldroid_ng.ui.chat.fragment.ChatFragment;
+import de.kuschku.quasseldroid_ng.ui.chat.fragment.LoadingFragment;
+import de.kuschku.quasseldroid_ng.ui.chat.util.ActivityImplFactory;
+import de.kuschku.quasseldroid_ng.ui.chat.util.ILayoutHelper;
+import de.kuschku.quasseldroid_ng.ui.chat.util.Status;
+import de.kuschku.quasseldroid_ng.util.accounts.AccountManager;
+
+import static de.kuschku.util.AndroidAssert.assertNotNull;
+
+public class MainActivity extends BoundActivity {
+
+    /**
+     * A helper to handle the different layout implementations
+     */
+    ILayoutHelper layoutHelper;
+
+    /**
+     * Host layout for content fragment, for example showing a loader or the chat
+     */
+    @Bind(R.id.content_host)
+    FrameLayout contentHost;
+
+    /**
+     * Main ActionBar
+     */
+    @Bind(R.id.toolbar)
+    Toolbar toolbar;
+
+    /**
+     * The left material drawer of this activity, depending on layout either in the layout hierarchy
+     * or at the left as pull-out menu
+     */
+    Drawer drawerLeft;
+
+    /**
+     * AccountHeader field for the bufferviewconfig header
+     */
+    AccountHeader accountHeader;
+
+    /**
+     * This object encapsulates the current status of the activity – opened bufferview, for example
+     */
+    Status status = new Status();
+
+    private AccountManager manager;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        ButterKnife.bind(this);
+        setSupportActionBar(toolbar);
+        layoutHelper = ActivityImplFactory.of(getResources().getBoolean(R.bool.isTablet), this);
+        accountHeader = buildAccountHeader();
+        drawerLeft = layoutHelper.buildDrawer(savedInstanceState, accountHeader, toolbar);
+
+        replaceFragment(new LoadingFragment());
+
+        manager = new AccountManager(this);
+    }
+
+    private void replaceFragment(Fragment fragment) {
+        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+        transaction.replace(R.id.content_host, fragment);
+        transaction.commit();
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        assertNotNull(outState);
+
+        super.onSaveInstanceState(outState);
+        status.onSaveInstanceState(outState);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        assertNotNull(savedInstanceState);
+
+        super.onRestoreInstanceState(savedInstanceState);
+        status.onRestoreInstanceState(savedInstanceState);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.chat, menu);
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_hide_events:
+                return true;
+            case R.id.action_reauth:
+                context.settings().lastAccount.set("");
+                finish();
+                return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+
+    private AccountHeader buildAccountHeader() {
+        return new AccountHeaderBuilder()
+                .withActivity(this)
+                .withCompactStyle(true)
+                .withHeaderBackground(R.drawable.bg1)
+                .withProfileImagesVisible(false)
+                .build();
+    }
+
+    public void onEventMainThread(ConnectionChangeEvent event) {
+        if (event.status == ConnectionChangeEvent.Status.CONNECTED) {
+            replaceFragment(new ChatFragment());
+        }
+    }
+
+    public void onConnectionChange(ConnectionChangeEvent.Status status) {
+        if (status == ConnectionChangeEvent.Status.CONNECTED) {
+            replaceFragment(new ChatFragment());
+        }
+    }
+
+    public void onEventMainThread(GeneralErrorEvent event) {
+
+    }
+
+    @Override
+    protected void onConnectToThread(@Nullable ClientBackgroundThread thread) {
+        super.onConnectToThread(thread);
+        if (thread == null)
+            connectToServer(manager.account(context.settings().lastAccount.get()));
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/Settings.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/Settings.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d3e09c2bc07764b1c6e02dc1b3fb5f962138edf
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/Settings.java
@@ -0,0 +1,62 @@
+/*
+ * 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 android.content.Context;
+import android.content.SharedPreferences;
+
+import aspm.BooleanPreference;
+import aspm.IntPreference;
+import aspm.StringPreference;
+import de.kuschku.util.backports.Objects;
+
+public class Settings {
+    public final StringPreference lastAccount;
+
+    public final IntPreference textSize;
+
+    public final BooleanPreference mircColors;
+
+    public final BooleanPreference fullHostmask;
+
+    public final StringPreference theme;
+
+    public Settings(SharedPreferences pref) {
+        this.lastAccount = new StringPreference(pref, "lastAccount", "");
+        this.textSize = new IntPreference(pref, "textSize", 2);
+        this.mircColors = new BooleanPreference(pref, "mircColors", true);
+        this.fullHostmask = new BooleanPreference(pref, "fullHostmask", false);
+        this.theme = new StringPreference(pref, "theme", "QUASSEL_LIGHT");
+
+        pref.registerOnSharedPreferenceChangeListener((preferences, key) -> {
+            if (Objects.equals(key, "lastAccount")) lastAccount.change();
+            if (Objects.equals(key, "textSize")) textSize.change();
+            if (Objects.equals(key, "mircColors")) mircColors.change();
+            if (Objects.equals(key, "fullHostmask")) fullHostmask.change();
+            if (Objects.equals(key, "theme")) theme.change();
+        });
+    }
+
+    public Settings(Context ctx) {
+        this(ctx.getSharedPreferences("de.kuschku.quasseldroid_ng", 0));
+    }
+}
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/drawer/NickListWrapper.java
similarity index 99%
rename from app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListWrapper.java
rename to app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NickListWrapper.java
index d55c3a6b6aea40ab99efa8733ea6b0e38029db0d..0e55bf39ad65bd26a388e4037b50bd56eec50e57 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListWrapper.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NickListWrapper.java
@@ -19,7 +19,7 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid_ng.ui.chat;
+package de.kuschku.quasseldroid_ng.ui.chat.drawer;
 
 import android.support.annotation.NonNull;
 
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
new file mode 100644
index 0000000000000000000000000000000000000000..3abb53736ea96f60cb88cc9f8ce35a7240c9a32e
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java
@@ -0,0 +1,107 @@
+/*
+ * 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.fragment;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.sothree.slidinguppanel.SlidingUpPanelLayout;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.libquassel.client.Client;
+import de.kuschku.libquassel.events.BacklogReceivedEvent;
+import de.kuschku.libquassel.events.BufferChangeEvent;
+import de.kuschku.libquassel.message.Message;
+import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.util.BoundFragment;
+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 static de.kuschku.util.AndroidAssert.assertNotNull;
+
+public class ChatFragment extends BoundFragment {
+    private SlidingPanelHandler panelHandler;
+    private MessageAdapter messageAdapter;
+
+    /**
+     * The list containing the messages to be displayed
+     */
+    @Bind(R.id.messages)
+    RecyclerView messages;
+
+    @Bind(R.id.swipe_view)
+    SwipeRefreshLayout swipeView;
+
+    @Bind(R.id.sliding_layout)
+    SlidingUpPanelLayout sliderMain;
+
+    @Nullable
+    @Override
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.fragment_chat, container, false);
+        panelHandler = new SlidingPanelHandler(getActivity(), (SlidingUpPanelLayout) view, context);
+        ButterKnife.bind(this, view);
+
+        assertNotNull(messages);
+
+        messages.setItemAnimator(new DefaultItemAnimator());
+        messages.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, true));
+        messageAdapter = new MessageAdapter(getActivity(), context, new AutoScroller(messages));
+        messages.setAdapter(messageAdapter);
+
+        swipeView.setColorSchemeColors(context.themeUtil().res.colorPrimary);
+        swipeView.setEnabled(false);
+
+        return view;
+    }
+
+    public void onEventMainThread(BufferChangeEvent event) {
+        Client client = context.client();
+        if (client != null) {
+            QBacklogManager<? extends QBacklogManager> backlogManager = client.backlogManager();
+            int id = backlogManager.open();
+            ObservableComparableSortedList<Message> messageList = backlogManager.filtered(id);
+            messageAdapter.setMessageList(messageList);
+            swipeView.setEnabled(id != -1);
+        } else {
+            swipeView.setEnabled(false);
+        }
+    }
+
+    public void onEventMainThread(BacklogReceivedEvent event) {
+        Client client = context.client();
+        if (client != null && client.backlogManager().open() == event.bufferId) {
+            swipeView.setRefreshing(false);
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java
new file mode 100644
index 0000000000000000000000000000000000000000..d88b873c305293e3f380e83fcfa418ee61cfe32e
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java
@@ -0,0 +1,99 @@
+/*
+ * 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.fragment;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.libquassel.events.BacklogInitEvent;
+import de.kuschku.libquassel.events.ConnectionChangeEvent;
+import de.kuschku.libquassel.events.InitEvent;
+import de.kuschku.libquassel.primitives.types.BufferInfo;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.util.BoundFragment;
+
+import static de.kuschku.util.AndroidAssert.assertNotNull;
+
+public class LoadingFragment extends BoundFragment {
+    @Bind(R.id.progressBar)
+    ProgressBar progressBar;
+
+    @Bind(R.id.label)
+    TextView label;
+
+    @Bind(R.id.count)
+    TextView count;
+
+    @Nullable
+    @Override
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.fragment_loading, container, false);
+        ButterKnife.bind(this, view);
+
+
+        label.setText("Connecting");
+        count.setText("");
+
+        return view;
+    }
+
+    public void onEventMainThread(ConnectionChangeEvent event) {
+        progressBar.setIndeterminate(true);
+
+        label.setText(event.status.name());
+        count.setText("");
+    }
+
+    public void onEventMainThread(InitEvent event) {
+        if (context.client().connectionStatus() == ConnectionChangeEvent.Status.INITIALIZING_DATA) {
+            progressBar.setIndeterminate(false);
+            progressBar.setMax(event.max);
+            progressBar.setProgress(event.loaded);
+
+            label.setText(event.getClass().getSimpleName());
+            count.setText(String.format("%d/%d", event.loaded, event.max));
+        }
+    }
+
+    public void onEventMainThread(BacklogInitEvent event) {
+        if (context.client().connectionStatus() == ConnectionChangeEvent.Status.LOADING_BACKLOG) {
+            progressBar.setIndeterminate(false);
+            progressBar.setMax(event.max);
+            progressBar.setProgress(event.loaded);
+
+            label.setText(event.getClass().getSimpleName());
+            count.setText(String.format("%d/%d", event.loaded, event.max));
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ActivityImplFactory.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ActivityImplFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..26e7f29faa8bc8eb6360920fabfaccb40a98c4f1
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ActivityImplFactory.java
@@ -0,0 +1,35 @@
+/*
+ * 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.util;
+
+import de.kuschku.quasseldroid_ng.ui.chat.MainActivity;
+
+public class ActivityImplFactory {
+    private ActivityImplFactory() {
+
+    }
+
+
+    public static ILayoutHelper of(boolean tablet, MainActivity activity) {
+        return (tablet) ? new LayoutHelperTabletImpl(activity) : new LayoutHelperPhoneImpl(activity);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ILayoutHelper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ILayoutHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..feb4315807186c7ec1e82e0c3e3809c5a86ba615
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ILayoutHelper.java
@@ -0,0 +1,33 @@
+/*
+ * 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.util;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.Toolbar;
+
+import com.mikepenz.materialdrawer.AccountHeader;
+import com.mikepenz.materialdrawer.Drawer;
+
+public interface ILayoutHelper {
+    Drawer buildDrawer(@Nullable Bundle savedInstanceState, AccountHeader accountHeader, Toolbar toolbar);
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperPhoneImpl.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperPhoneImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8b7775705a3ab4ccfea36ca913237376753d581
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperPhoneImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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.util;
+
+import android.os.Bundle;
+import android.support.v7.widget.Toolbar;
+
+import com.mikepenz.materialdrawer.AccountHeader;
+import com.mikepenz.materialdrawer.Drawer;
+import com.mikepenz.materialdrawer.DrawerBuilder;
+
+import de.kuschku.quasseldroid_ng.ui.chat.MainActivity;
+
+public class LayoutHelperPhoneImpl implements ILayoutHelper {
+    private final MainActivity activity;
+
+    public LayoutHelperPhoneImpl(MainActivity activity) {
+        this.activity = activity;
+    }
+
+    @Override
+    public Drawer buildDrawer(Bundle savedInstanceState, AccountHeader accountHeader, Toolbar toolbar) {
+        return new DrawerBuilder()
+                .withActivity(activity)
+                .withToolbar(toolbar)
+                .withAccountHeader(accountHeader)
+                .withTranslucentStatusBar(true)
+                .withSavedInstance(savedInstanceState)
+                .build();
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperTabletImpl.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperTabletImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ced622bc146ff0cb6ee64abe4f81c568d693cfe
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/LayoutHelperTabletImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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.util;
+
+import android.os.Bundle;
+import android.support.v7.widget.Toolbar;
+import android.widget.FrameLayout;
+
+import com.mikepenz.materialdrawer.AccountHeader;
+import com.mikepenz.materialdrawer.Drawer;
+import com.mikepenz.materialdrawer.DrawerBuilder;
+
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.chat.MainActivity;
+
+public class LayoutHelperTabletImpl implements ILayoutHelper {
+    private final MainActivity activity;
+
+    public LayoutHelperTabletImpl(MainActivity activity) {
+        this.activity = activity;
+    }
+
+    @Override
+    public Drawer buildDrawer(Bundle savedInstanceState, AccountHeader accountHeader, Toolbar toolbar) {
+        Drawer drawer = new DrawerBuilder()
+                .withActivity(activity)
+                .withToolbar(toolbar)
+                .withAccountHeader(accountHeader)
+                .withTranslucentStatusBar(false)
+                .withSavedInstance(savedInstanceState)
+                .buildView();
+        FrameLayout drawerHost = (FrameLayout) activity.findViewById(R.id.drawer_host);
+        drawerHost.addView(drawer.getSlider());
+        return drawer;
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ServiceHelper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ServiceHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b810f20fa23fcfa8f8fd2b3dd349659ed27f8a3
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/ServiceHelper.java
@@ -0,0 +1,76 @@
+/*
+ * 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.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+
+import de.kuschku.quasseldroid_ng.service.QuasselService;
+import de.kuschku.quasseldroid_ng.ui.chat.Settings;
+import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+import de.kuschku.quasseldroid_ng.ui.theme.AppTheme;
+import de.kuschku.quasseldroid_ng.ui.theme.ThemeUtil;
+
+public class ServiceHelper {
+    private ServiceHelper() {
+    }
+
+    /**
+     * Connects to an already running QuasselService
+     * @param context The context in which the service is running
+     * @param connection The connection to which it should be bound
+     */
+    public static void connectToService(Context context, ServiceConnection connection) {
+        Intent intent = new Intent(context, QuasselService.class);
+        context.bindService(intent, connection, Context.BIND_IMPORTANT);
+    }
+
+    /**
+     * Connects to an already running QuasselService
+     * @param context The context in which the service is running
+     * @param connection The connection which should be disconnected
+     */
+    public static void disconnect(Context context, ServiceConnection connection) {
+        context.unbindService(connection);
+    }
+
+    /**
+     * Starts a new QuasselService, if not yet running.
+     * @param context The context in which it should run
+     */
+    public static void startServiceIfNotRunning(Context context) {
+        Intent intent = new Intent(context, QuasselService.class);
+        context.startService(intent);
+    }
+
+    public static void initTheme(AppContext context, Activity activity) {
+        // Init SharedPreferences
+        Settings settings = new Settings(activity);
+        context.setSettings(settings);
+        // Load Theme from Preferences
+        AppTheme theme = AppTheme.themeFromString(settings.theme.get());
+        activity.setTheme(theme.themeId);
+        context.setThemeUtil(new ThemeUtil(activity, theme));
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/SlidingPanelHandler.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/SlidingPanelHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f02e84a2f00ebffea4d6b1af393310b66fd5976
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/SlidingPanelHandler.java
@@ -0,0 +1,211 @@
+/*
+ * 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.util;
+
+import android.app.Activity;
+import android.support.v7.widget.ActionMenuView;
+import android.support.v7.widget.AppCompatEditText;
+import android.support.v7.widget.AppCompatImageButton;
+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.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.mikepenz.fastadapter.FastAdapter;
+import com.mikepenz.fastadapter.IItem;
+import com.mikepenz.fastadapter.adapters.ItemAdapter;
+import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
+import com.sothree.slidinguppanel.SlidingUpPanelLayout;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.editor.AdvancedEditor;
+import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+import de.kuschku.quasseldroid_ng.ui.theme.ThemeUtil;
+
+import static de.kuschku.util.AndroidAssert.assertNotNull;
+
+public class SlidingPanelHandler {
+    private final Activity activity;
+    private final AppContext context;
+    private final AdvancedEditor editor;
+
+    // Main Sliding Layout
+    SlidingUpPanelLayout slidingLayout;
+
+    // Input History
+    @Bind(R.id.sliding_layout_history)
+    SlidingUpPanelLayout slidingLayoutHistory;
+    @Bind(R.id.msg_history)
+    RecyclerView msgHistory;
+
+    // Advanced Formatter
+    @Bind(R.id.formatting_menu)
+    ActionMenuView formattingMenu;
+    @Bind(R.id.formatting_toolbar)
+    Toolbar formattingToolbar;
+
+    // Input Line
+    @Bind(R.id.chatline)
+    AppCompatEditText chatline;
+    @Bind(R.id.send)
+    AppCompatImageButton send;
+
+    public SlidingPanelHandler(Activity activity, SlidingUpPanelLayout slidingLayout, AppContext context) {
+        this.slidingLayout = slidingLayout;
+        ButterKnife.bind(this, slidingLayout);
+        this.activity = activity;
+        this.context = context;
+        this.editor = new AdvancedEditor(context, chatline);
+
+        setupFormattingMenu(activity);
+
+        setupHistoryFakeData();
+
+        bindListener();
+    }
+
+    private void setupFormattingMenu(Activity activity) {
+        activity.getMenuInflater().inflate(R.menu.formatting, formattingMenu.getMenu());
+        formattingMenu.setOnMenuItemClickListener(item -> {
+            switch (item.getItemId()) {
+                case R.id.format_bold:
+                    editor.toggleBold();
+                    return true;
+                case R.id.format_italic:
+                    editor.toggleItalic();
+                    return true;
+                case R.id.format_underline:
+                    editor.toggleUnderline();
+                    return true;
+                case R.id.action_history:
+                    openHistory();
+                    return true;
+                default:
+                    return false;
+            }
+        });
+    }
+
+    public void setFormattingEnabled(boolean formattingEnabled) {
+        Menu menu = formattingMenu.getMenu();
+        MenuItem[] items = new MenuItem[]{
+                menu.findItem(R.id.format_bold),
+                menu.findItem(R.id.format_italic),
+                menu.findItem(R.id.format_underline),
+                menu.findItem(R.id.format_paint),
+                menu.findItem(R.id.format_fill)
+        };
+
+        for (MenuItem item : items) {
+            if (item != null)
+                item.setEnabled(!formattingEnabled);
+        }
+    }
+
+    private void setChatlineExpanded(boolean expanded) {
+        assertNotNull(chatline);
+        assertNotNull(chatline.getLayoutParams());
+
+        ThemeUtil themeUtil = context.themeUtil();
+        assertNotNull(themeUtil);
+
+        int selectionStart = chatline.getSelectionStart();
+        int selectionEnd = chatline.getSelectionEnd();
+
+        if (expanded) {
+            chatline.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
+        } else {
+            chatline.getLayoutParams().height = themeUtil.res.actionBarSize;
+        }
+        chatline.setSingleLine(!expanded);
+
+        chatline.setSelection(selectionStart, selectionEnd);
+    }
+
+    private void bindListener() {
+        slidingLayout.setAntiDragView(R.id.card_panel);
+        slidingLayout.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() {
+            @Override
+            public void onPanelSlide(View panel, float slideOffset) {
+
+            }
+
+            @Override
+            public void onPanelCollapsed(View panel) {
+                setChatlineExpanded(false);
+            }
+
+            @Override
+            public void onPanelExpanded(View panel) {
+                setChatlineExpanded(true);
+            }
+
+            @Override
+            public void onPanelAnchored(View panel) {
+
+            }
+
+            @Override
+            public void onPanelHidden(View panel) {
+
+            }
+        });
+        setChatlineExpanded(slidingLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED);
+    }
+
+    private void setupHistoryFakeData() {
+        FastAdapter<IItem> fastAdapter = new FastAdapter<>();
+        ItemAdapter<IItem> itemAdapter = new ItemAdapter<>();
+        itemAdapter.wrap(fastAdapter);
+        itemAdapter.add(
+                new PrimaryDrawerItem().withName("Entry #1"),
+                new PrimaryDrawerItem().withName("Entry #2"),
+                new PrimaryDrawerItem().withName("Entry #3"),
+                new PrimaryDrawerItem().withName("Entry #4"),
+                new PrimaryDrawerItem().withName("Entry #5"),
+                new PrimaryDrawerItem().withName("Entry #6"),
+                new PrimaryDrawerItem().withName("Entry #7"),
+                new PrimaryDrawerItem().withName("Entry #8"),
+                new PrimaryDrawerItem().withName("Entry #9"),
+                new PrimaryDrawerItem().withName("Entry #10"),
+                new PrimaryDrawerItem().withName("Entry #11"),
+                new PrimaryDrawerItem().withName("Entry #12"),
+                new PrimaryDrawerItem().withName("Entry #13"),
+                new PrimaryDrawerItem().withName("Entry #14"),
+                new PrimaryDrawerItem().withName("Entry #15"),
+                new PrimaryDrawerItem().withName("Entry #16")
+        );
+        msgHistory.setAdapter(fastAdapter);
+        msgHistory.setLayoutManager(new LinearLayoutManager(activity));
+        msgHistory.setItemAnimator(new DefaultItemAnimator());
+    }
+
+    private void openHistory() {
+        slidingLayoutHistory.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/Status.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/Status.java
new file mode 100644
index 0000000000000000000000000000000000000000..15eb3f9b3e553c3c3e7ec65229e0d04e758fbcd1
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/util/Status.java
@@ -0,0 +1,30 @@
+/*
+ * 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.util;
+
+import de.kuschku.util.instancestateutil.Storable;
+import de.kuschku.util.instancestateutil.Store;
+
+public class Status extends Storable {
+    @Store
+    int bufferViewConfigId = -1;
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..2be3d7ecfa55649e0b8ee514031fcb1dc63cb0b6
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountItem.java
@@ -0,0 +1,163 @@
+/*
+ * 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.setup;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.support.annotation.ColorInt;
+import android.support.v7.widget.AppCompatRadioButton;
+import android.support.v7.widget.RecyclerView;
+import android.util.Pair;
+import android.view.View;
+import android.widget.TextView;
+
+import com.mikepenz.fastadapter.utils.ViewHolderFactory;
+import com.mikepenz.materialdrawer.model.AbstractDrawerItem;
+import com.mikepenz.materialdrawer.util.DrawerUIUtils;
+
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.util.accounts.Account;
+
+public class AccountItem extends AbstractDrawerItem<AccountItem, AccountItem.ViewHolder> {
+    public final Account account;
+
+    public AccountItem(Account account) {
+        this.account = account;
+    }
+
+    @Override
+    public int getType() {
+        return R.id.item_account;
+    }
+
+    @Override
+    public int getLayoutRes() {
+        return R.layout.widget_core_account;
+    }
+
+    @Override
+    public boolean isSelectable() {
+        return true;
+    }
+
+    @Override
+    public void bindView(ViewHolder viewHolder) {
+        Context ctx = viewHolder.itemView.getContext();
+
+        //set the identifier from the drawerItem here. It can be used to run tests
+        viewHolder.itemView.setId(hashCode());
+
+        //set the item selected if it is
+        viewHolder.itemView.setSelected(isSelected());
+
+        //get the correct color for the text
+        int color = getColor(ctx);
+        int selectedTextColor = getSelectedTextColor(ctx);
+
+        viewHolder.name.setText(account.name);
+
+        viewHolder.select.setChecked(isSelected());
+        viewHolder.select.setClickable(false);
+
+        viewHolder.description.setText(viewHolder.itemView.getContext().getString(R.string.labelUserOnHost, account.user, account.host));
+
+        viewHolder.name.setTextColor(getTextColorStateList(color, selectedTextColor));
+
+        viewHolder.description.setTextColor(getTextColorStateList(color, selectedTextColor));
+
+        //for android API 17 --> Padding not applied via xml
+        DrawerUIUtils.setDrawerVerticalPadding(viewHolder.view);
+
+        //call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
+        onPostBindView(this, viewHolder.itemView);
+    }
+
+    @Override
+    public ViewHolderFactory getFactory() {
+        return new ItemFactory();
+    }
+
+    public static class ItemFactory implements ViewHolderFactory<ViewHolder> {
+        public ViewHolder create(View v) {
+            return new ViewHolder(v);
+        }
+    }
+
+    protected static class ViewHolder extends RecyclerView.ViewHolder {
+        private View view;
+        private AppCompatRadioButton select;
+        private TextView name;
+        private TextView description;
+
+        private ViewHolder(View view) {
+            super(view);
+            this.view = view;
+            this.select = (AppCompatRadioButton) view.findViewById(R.id.account_select);
+            this.name = (TextView) view.findViewById(R.id.account_name);
+            this.description = (TextView) view.findViewById(R.id.account_description);
+        }
+    }
+
+
+    /**
+     * helper method to decide for the correct color
+     *
+     * @param ctx
+     * @return
+     */
+    protected int getColor(Context ctx) {
+        int color;
+        if (this.isEnabled()) {
+            color = com.mikepenz.materialdrawer.R.color.material_drawer_primary_text;
+        } else {
+            color = com.mikepenz.materialdrawer.R.color.material_drawer_hint_text;
+        }
+        return color;
+    }
+
+    /**
+     * helper method to decide for the correct color
+     *
+     * @param ctx
+     * @return
+     */
+    protected int getSelectedTextColor(Context ctx) {
+        return com.mikepenz.materialdrawer.R.color.material_drawer_selected_text;
+    }
+
+    protected Pair<Integer, ColorStateList> colorStateList;
+
+    /**
+     * helper to get the ColorStateList for the text and remembering it so we do not have to recreate it all the time
+     *
+     * @param color
+     * @param selectedTextColor
+     * @return
+     */
+    protected ColorStateList getTextColorStateList(@ColorInt int color, @ColorInt int selectedTextColor) {
+        if (colorStateList == null || color + selectedTextColor != colorStateList.first) {
+            colorStateList = new Pair<>(color + selectedTextColor, DrawerUIUtils.getTextColorStateList(color, selectedTextColor));
+        }
+
+        return colorStateList.second;
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSelectActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSelectActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..bba27567a72d9a40261c387086606df9fd3794be
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSelectActivity.java
@@ -0,0 +1,94 @@
+/*
+ * 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.setup;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSelectSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.SlideFragment;
+
+public class AccountSelectActivity extends AppCompatActivity {
+    private SlidePagerAdapter slidePagerAdapter;
+
+    @Bind(R.id.view_pager)
+    ViewPager viewPager;
+
+    @Bind(R.id.btn)
+    FloatingActionButton btn;
+
+    private class SlidePagerAdapter extends FragmentPagerAdapter {
+        private SlideFragment item = new AccountSelectSlide();
+
+        public SlidePagerAdapter(FragmentManager fm) {
+            super(fm);
+        }
+
+        @Override
+        public SlideFragment getItem(int position) {
+            return item;
+        }
+
+        @Override
+        public int getCount() {
+            return 1;
+        }
+    }
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_setup);
+        ButterKnife.bind(this);
+        slidePagerAdapter = new SlidePagerAdapter(getSupportFragmentManager());
+
+        viewPager.setAdapter(slidePagerAdapter);
+        slidePagerAdapter.notifyDataSetChanged();
+        updateValidity(slidePagerAdapter.item.isValid());
+        btn.setImageResource(R.drawable.ic_check_dark);
+        slidePagerAdapter.item.addChangeListener(this::updateValidity);
+        btn.setOnClickListener(v -> {
+            Bundle bundle = new Bundle();
+            slidePagerAdapter.item.getData(bundle);
+
+            Intent result = new Intent();
+            result.putExtra("extra", bundle);
+            setResult(RESULT_OK, result);
+            finish();
+        });
+    }
+
+    public void updateValidity(boolean validity) {
+        btn.setVisibility(validity ? View.VISIBLE : View.GONE);
+        slidePagerAdapter.notifyDataSetChanged();
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSetupActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSetupActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..f424544ba01825d4f28e61b1eef8561f4f4532d1
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/AccountSetupActivity.java
@@ -0,0 +1,172 @@
+/*
+ * 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.setup;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupCoreSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupNameSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupUserSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.SlideFragment;
+import de.kuschku.quasseldroid_ng.util.accounts.Account;
+import de.kuschku.quasseldroid_ng.util.accounts.AccountManager;
+
+public class AccountSetupActivity extends AppCompatActivity implements ValidUpdateCallback {
+
+    private SlidePagerAdapter slidePagerAdapter;
+
+    @Bind(R.id.view_pager)
+    ViewPager viewPager;
+
+    @Bind(R.id.btn)
+    FloatingActionButton btn;
+
+    private int lastValidPage = -1;
+
+    private class SlidePagerAdapter extends FragmentPagerAdapter {
+        List<SlideFragment> list = new ArrayList<>();
+
+        public SlidePagerAdapter(FragmentManager fm) {
+            super(fm);
+        }
+
+        @Override
+        public SlideFragment getItem(int position) {
+            return list.get(position);
+        }
+
+        @Override
+        public int getCount() {
+            return Math.min(lastValidPage + 2, list.size());
+        }
+
+        public void addFragment(SlideFragment fragment) {
+            list.add(fragment);
+            notifyDataSetChanged();
+        }
+    }
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_setup);
+        ButterKnife.bind(this);
+
+        slidePagerAdapter = new SlidePagerAdapter(getSupportFragmentManager());
+        viewPager.setAdapter(slidePagerAdapter);
+
+        slidePagerAdapter.addFragment(new AccountSetupCoreSlide());
+        slidePagerAdapter.addFragment(new AccountSetupUserSlide());
+        slidePagerAdapter.addFragment(new AccountSetupNameSlide());
+
+        SlideFragment item = slidePagerAdapter.getItem(viewPager.getCurrentItem());
+
+        updateValidity(item.isValid());
+
+        btn.setOnClickListener(v -> {
+            if (viewPager.getCurrentItem() == slidePagerAdapter.getCount() - 1) {
+                onDone();
+            } else {
+                viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true);
+            }
+        });
+
+        slidePagerAdapter.getItem(viewPager.getCurrentItem()).addChangeListener(AccountSetupActivity.this);
+        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+            @Override
+            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+
+            }
+
+            @Override
+            public void onPageSelected(int position) {
+                SlideFragment slideFragment = slidePagerAdapter.getItem(viewPager.getCurrentItem());
+                for (int i = 0; i < slidePagerAdapter.getCount(); i++) {
+                    slidePagerAdapter.getItem(i).removeChangeListener(AccountSetupActivity.this);
+                }
+                slideFragment.addChangeListener(AccountSetupActivity.this);
+                updateValidity(slideFragment.isValid());
+                if (viewPager.getCurrentItem() == slidePagerAdapter.list.size() - 1) {
+                    btn.setImageResource(R.drawable.ic_check_dark);
+                } else {
+                    btn.setImageResource(R.drawable.ic_arrow_right_dark);
+                }
+            }
+
+            @Override
+            public void onPageScrollStateChanged(int state) {
+
+            }
+        });
+    }
+
+    private void onDone() {
+        Bundle bundle = new Bundle();
+        for (SlideFragment fragment : slidePagerAdapter.list) {
+            fragment.getData(bundle);
+        }
+
+        setupAccount(bundle);
+
+        Intent result = new Intent();
+        result.putExtra("extra", bundle);
+        setResult(RESULT_OK, result);
+        finish();
+    }
+
+    private void setupAccount(Bundle bundle) {
+        AccountManager manager = new AccountManager(this);
+        manager.add(new Account(
+                UUID.randomUUID(),
+                bundle.getString("name"),
+                bundle.getString("host"),
+                bundle.getInt("port"),
+                bundle.getString("user"),
+                bundle.getString("pass")
+        ));
+    }
+
+    public void updateValidity(boolean validity) {
+        btn.setVisibility(validity ? View.VISIBLE : View.GONE);
+        if (validity) {
+            lastValidPage = viewPager.getCurrentItem();
+        } else {
+            lastValidPage = viewPager.getCurrentItem() - 1;
+        }
+        slidePagerAdapter.notifyDataSetChanged();
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CreateAccountItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CreateAccountItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..550abdb3dc05f78a72bb1040cefbd63b1e4bc900
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CreateAccountItem.java
@@ -0,0 +1,129 @@
+/*
+ * 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.setup;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.support.annotation.ColorInt;
+import android.support.v7.widget.AppCompatRadioButton;
+import android.support.v7.widget.RecyclerView;
+import android.util.Pair;
+import android.view.View;
+import android.widget.TextView;
+
+import com.mikepenz.fastadapter.utils.ViewHolderFactory;
+import com.mikepenz.materialdrawer.model.AbstractDrawerItem;
+import com.mikepenz.materialdrawer.util.DrawerUIUtils;
+
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.util.accounts.Account;
+
+public class CreateAccountItem extends AbstractDrawerItem<CreateAccountItem, CreateAccountItem.ViewHolder> {
+    @Override
+    public int getType() {
+        return R.id.item_create_account;
+    }
+
+    @Override
+    public int getLayoutRes() {
+        return R.layout.widget_core_account_add;
+    }
+
+    @Override
+    public void bindView(ViewHolder viewHolder) {
+        //set the identifier from the drawerItem here. It can be used to run tests
+        viewHolder.itemView.setId(hashCode());
+
+        //set the item selected if it is
+        viewHolder.itemView.setSelected(isSelected());
+
+        //for android API 17 --> Padding not applied via xml
+        DrawerUIUtils.setDrawerVerticalPadding(viewHolder.view);
+
+        //call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
+        onPostBindView(this, viewHolder.itemView);
+    }
+
+    @Override
+    public ViewHolderFactory getFactory() {
+        return new ItemFactory();
+    }
+
+    public static class ItemFactory implements ViewHolderFactory<ViewHolder> {
+        public ViewHolder create(View v) {
+            return new ViewHolder(v);
+        }
+    }
+
+    protected static class ViewHolder extends RecyclerView.ViewHolder {
+        private View view;
+
+        private ViewHolder(View view) {
+            super(view);
+            this.view = view;
+        }
+    }
+
+
+    /**
+     * helper method to decide for the correct color
+     *
+     * @param ctx
+     * @return
+     */
+    protected int getColor(Context ctx) {
+        int color;
+        if (this.isEnabled()) {
+            color = com.mikepenz.materialdrawer.R.color.material_drawer_primary_text;
+        } else {
+            color = com.mikepenz.materialdrawer.R.color.material_drawer_hint_text;
+        }
+        return color;
+    }
+
+    /**
+     * helper method to decide for the correct color
+     *
+     * @param ctx
+     * @return
+     */
+    protected int getSelectedTextColor(Context ctx) {
+        return com.mikepenz.materialdrawer.R.color.material_drawer_selected_text;
+    }
+
+    protected Pair<Integer, ColorStateList> colorStateList;
+
+    /**
+     * helper to get the ColorStateList for the text and remembering it so we do not have to recreate it all the time
+     *
+     * @param color
+     * @param selectedTextColor
+     * @return
+     */
+    protected ColorStateList getTextColorStateList(@ColorInt int color, @ColorInt int selectedTextColor) {
+        if (colorStateList == null || color + selectedTextColor != colorStateList.first) {
+            colorStateList = new Pair<>(color + selectedTextColor, DrawerUIUtils.getTextColorStateList(color, selectedTextColor));
+        }
+
+        return colorStateList.second;
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/ValidUpdateCallback.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/ValidUpdateCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..05328f0858f0f727ceb165c67ec8b9d9bebcc9ff
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/ValidUpdateCallback.java
@@ -0,0 +1,26 @@
+/*
+ * 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.setup;
+
+public interface ValidUpdateCallback {
+    void updateValidity(boolean isValid);
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSelectSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSelectSlide.java
new file mode 100644
index 0000000000000000000000000000000000000000..68947dc15cee466415631ae1dea1c00f84addd77
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSelectSlide.java
@@ -0,0 +1,148 @@
+/*
+ * 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.setup.slides;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.mikepenz.fastadapter.FastAdapter;
+import com.mikepenz.fastadapter.IItem;
+import com.mikepenz.fastadapter.adapters.ItemAdapter;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.setup.AccountItem;
+import de.kuschku.quasseldroid_ng.ui.setup.AccountSetupActivity;
+import de.kuschku.quasseldroid_ng.ui.setup.CreateAccountItem;
+import de.kuschku.quasseldroid_ng.util.accounts.Account;
+import de.kuschku.quasseldroid_ng.util.accounts.AccountManager;
+import de.kuschku.util.backports.Optional;
+import de.kuschku.util.backports.Optionals;
+
+public class AccountSelectSlide extends SlideFragment {
+    private ItemAdapter<IItem> itemAdapter;
+    private FastAdapter<IItem> fastAdapter;
+    private AccountManager manager;
+
+    @Override
+    public Bundle getData(Bundle in) {
+        AccountItem item =  (AccountItem) findAny(fastAdapter.getSelectedItems()).get();
+        in.putString("account", item.account.id.toString());
+        return in;
+    }
+
+    private <T> Optional<T> findAny(Set<T> selections) {
+        Iterator<T> iterator = selections.iterator();
+        if (iterator.hasNext()) {
+            return Optionals.of(iterator.next());
+        } else {
+            return Optionals.absent();
+        }
+    }
+
+    @Override
+    public boolean isValid() {
+        return fastAdapter != null && fastAdapter.getSelections().size() == 1 && findAny(fastAdapter.getSelectedItems()).get() instanceof AccountItem;
+    }
+
+    @Override
+    protected View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) {
+        RecyclerView recyclerView = (RecyclerView) inflater.inflate(R.layout.slide_select, container, false);
+
+        manager = new AccountManager(getContext());
+
+        fastAdapter = new FastAdapter<>();
+        itemAdapter = new ItemAdapter<>();
+        itemAdapter.wrap(fastAdapter);
+        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        recyclerView.setItemAnimator(new DefaultItemAnimator());
+        updateContent(true);
+        recyclerView.setAdapter(fastAdapter);
+
+        fastAdapter.withSelectWithItemUpdate(true);
+        fastAdapter.withOnClickListener((v, adapter, item, position) -> {
+            if (item instanceof CreateAccountItem) {
+                createNew();
+                return true;
+            } else {
+                fastAdapter.deselect();
+                fastAdapter.select(position);
+                updateValidity();
+                return false;
+            }
+        });
+
+
+        return recyclerView;
+    }
+
+    private void createNew() {
+        Intent intent = new Intent(getContext(), AccountSetupActivity.class);
+        startActivityForResult(intent, 0);
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (findAny(fastAdapter.getSelectedItems()).get() instanceof CreateAccountItem)
+            fastAdapter.deselect();
+
+        super.onActivityResult(requestCode, resultCode, data);
+        if (resultCode == Activity.RESULT_OK) {
+            updateContent(false);
+        } else if (fastAdapter.getItemCount() == 0) {
+            getActivity().finish();
+        }
+    }
+
+    private void updateContent(boolean autoCreate) {
+        itemAdapter.clear();
+        Set<Account> accounts = manager.accounts();
+        for (Account account : accounts) {
+            itemAdapter.add(new AccountItem(account));
+        }
+        itemAdapter.add(new CreateAccountItem());
+
+        if (accounts.size() == 0) {
+            createNew();
+        }
+    }
+
+    @Override
+    protected int getTitle() {
+        return R.string.slideAccountselectTitle;
+    }
+
+    @Override
+    protected int getDescription() {
+        return R.string.slideAccountselectDescription;
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java
new file mode 100644
index 0000000000000000000000000000000000000000..92745729bcf43fd5f9347006980f769c91028ff0
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java
@@ -0,0 +1,118 @@
+/*
+ * 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.setup.slides;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.v7.widget.AppCompatEditText;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.quasseldroid_ng.R;
+
+public class AccountSetupCoreSlide extends SlideFragment {
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Bind(R.id.host)
+    AppCompatEditText hostField;
+
+    @Bind(R.id.port)
+    AppCompatEditText portField;
+
+    @Override
+    protected View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.slide_account_core, container, false);
+        ButterKnife.bind(this, view);
+        hostField.addTextChangedListener(watcher);
+        portField.addTextChangedListener(watcher);
+        return view;
+    }
+
+    @Override
+    public Bundle getData(Bundle in) {
+        in.putString("host", hostField.getText().toString());
+        in.putInt("port", Integer.valueOf(portField.getText().toString()));
+        return in;
+    }
+
+    @Override
+    public boolean isValid() {
+        return validHost() && validPort();
+    }
+
+    @Override
+    @StringRes
+    public int getTitle() {
+        return R.string.slideAccountcoreTitle;
+    }
+
+    @Override
+    @StringRes
+    public int getDescription() {
+        return R.string.slideAccountcoreDescription;
+    }
+
+    private boolean validPort() {
+        if (portField == null)
+            return false;
+
+        String portText = portField.getText().toString();
+        try {
+            int port = Integer.parseInt(portText);
+            return port <= 65536 && port > 0;
+        } catch (NumberFormatException e) {
+            return false;
+        }
+    }
+
+    private boolean validHost() {
+        if (hostField == null)
+            return false;
+
+        String hostText = hostField.getText().toString();
+        return !hostText.isEmpty();
+    }
+
+    TextWatcher watcher = new TextWatcher() {
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            updateValidity();
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+        }
+    };
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java
new file mode 100644
index 0000000000000000000000000000000000000000..b50ae81d6527da31afaabe2c448c1fc7e9149f9f
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java
@@ -0,0 +1,100 @@
+/*
+ * 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.setup.slides;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.v7.widget.AppCompatEditText;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.quasseldroid_ng.R;
+
+public class AccountSetupNameSlide extends SlideFragment {
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Bind(R.id.name)
+    AppCompatEditText nameField;
+
+    @Override
+    protected View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.slide_account_name, container, false);
+        ButterKnife.bind(this, view);
+        nameField.addTextChangedListener(watcher);
+        return view;
+    }
+
+    @Override
+    public Bundle getData(Bundle in) {
+        in.putString("name", nameField.getText().toString());
+        return in;
+    }
+
+    @Override
+    public boolean isValid() {
+        return validName();
+    }
+
+    @Override
+    @StringRes
+    public int getTitle() {
+        return R.string.slideAccountnameTitle;
+    }
+
+    @Override
+    @StringRes
+    public int getDescription() {
+        return R.string.slideAccountnameDescription;
+    }
+
+    private boolean validName() {
+        if (nameField == null)
+            return false;
+
+        String hostText = nameField.getText().toString();
+        return !hostText.isEmpty();
+    }
+
+    TextWatcher watcher = new TextWatcher() {
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            updateValidity();
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+        }
+    };
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6b77f179eda08de4b5ceba3a827dccdda8b5e89
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java
@@ -0,0 +1,113 @@
+/*
+ * 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.setup.slides;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.v7.widget.AppCompatEditText;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.quasseldroid_ng.R;
+
+public class AccountSetupUserSlide extends SlideFragment {
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Bind(R.id.user)
+    AppCompatEditText userField;
+
+    @Bind(R.id.pass)
+    AppCompatEditText passField;
+
+    @Override
+    public View onCreateContent(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.slide_account_user, container, false);
+        ButterKnife.bind(this, view);
+        userField.addTextChangedListener(watcher);
+        passField.addTextChangedListener(watcher);
+        return view;
+    }
+
+    @Override
+    public Bundle getData(Bundle in) {
+        in.putString("user", userField.getText().toString());
+        in.putString("pass", passField.getText().toString());
+        return in;
+    }
+
+    @Override
+    public boolean isValid() {
+        return validUser() && validPass();
+    }
+
+    @Override
+    @StringRes
+    public int getTitle() {
+        return R.string.slideAccountuserTitle;
+    }
+
+    @Override
+    @StringRes
+    public int getDescription() {
+        return R.string.slideAccountuserDescription;
+    }
+
+    private boolean validUser() {
+        if (userField == null)
+            return false;
+
+        String hostText = userField.getText().toString();
+        return !hostText.isEmpty();
+    }
+
+    private boolean validPass() {
+        if (passField == null)
+            return false;
+
+        String hostText = passField.getText().toString();
+        return !hostText.isEmpty();
+    }
+
+    TextWatcher watcher = new TextWatcher() {
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+            updateValidity();
+        }
+    };
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0f460dc66bcdce5adc30a669e31a46c1b1aff70
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java
@@ -0,0 +1,80 @@
+/*
+ * 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.setup.slides;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.setup.ValidUpdateCallback;
+
+public abstract class SlideFragment extends Fragment {
+    private Set<ValidUpdateCallback> callbacks = new HashSet<>();
+
+    public abstract Bundle getData(Bundle in);
+
+
+    public abstract boolean isValid();
+    public void addChangeListener(ValidUpdateCallback callback) {
+        callbacks.add(callback);
+    }
+    public void removeChangeListener(ValidUpdateCallback callback) {
+        callbacks.remove(callback);
+    }
+    protected void updateValidity() {
+        updateValidity(isValid());
+    }
+    protected void updateValidity(boolean validity) {
+        for (ValidUpdateCallback callback : callbacks) {
+            callback.updateValidity(validity);
+        }
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.slide, container, false);
+        ViewGroup viewGroup = (ViewGroup) view.findViewById(R.id.content_host);
+        viewGroup.addView(onCreateContent(inflater, viewGroup, savedInstanceState));
+
+        ((TextView) view.findViewById(R.id.title)).setText(getTitle());
+        ((TextView) view.findViewById(R.id.description)).setText(getDescription());
+
+        return view;
+    }
+    protected abstract View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState);
+
+    @StringRes
+    protected abstract int getTitle();
+
+    @StringRes
+    protected abstract int getDescription();
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppContext.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppContext.java
index 1ff313ca85c30483000c2f234893802f6a99a5a0..3ccec30be24c1207e20aa7c4d809eb0dbde20bc9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppContext.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppContext.java
@@ -25,11 +25,11 @@ import android.support.annotation.NonNull;
 
 import de.kuschku.libquassel.BusProvider;
 import de.kuschku.libquassel.client.Client;
-import de.kuschku.quasseldroid_ng.ui.chat.WrappedSettings;
+import de.kuschku.quasseldroid_ng.ui.chat.Settings;
 
 public class AppContext {
     private ThemeUtil themeUtil;
-    private WrappedSettings settings;
+    private Settings settings;
     private Client client;
     private BusProvider provider;
 
@@ -47,16 +47,16 @@ public class AppContext {
         return this;
     }
 
-    public WrappedSettings settings() {
+    public Settings settings() {
         return settings;
     }
 
-    public void setSettings(WrappedSettings settings) {
+    public void setSettings(Settings settings) {
         this.settings = settings;
     }
 
     @NonNull
-    public AppContext withSettings(WrappedSettings settings) {
+    public AppContext withSettings(Settings settings) {
         setSettings(settings);
         return this;
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppTheme.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppTheme.java
index fc645268fee9d2e412828d1a47677bb02299faa1..033e43242990fa180f396a862e5998b4b5aa18c0 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppTheme.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/AppTheme.java
@@ -31,7 +31,8 @@ public enum AppTheme {
     QUASSEL_LIGHT(R.style.Quassel_Light),
     QUASSEL_DARK(R.style.Quassel_Dark),
     MATERIAL_DARK(R.style.Material_Dark),
-    MATERIAL_LIGHT(R.style.Material_Light);
+    MATERIAL_LIGHT(R.style.Material_Light),
+    SOLARIZED_DARK(R.style.Solarized_Dark);
 
     public final int themeId;
 
@@ -53,6 +54,8 @@ public enum AppTheme {
                 return MATERIAL_LIGHT;
             case "QUASSEL_DARK":
                 return QUASSEL_DARK;
+            case "SOLARIZED_DARK":
+                return SOLARIZED_DARK;
 
             default:
             case "QUASSEL_LIGHT":
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java
index d9ff61586e787b43e451c7daa01c0c5209ac9515..32b44f69ac1d39aae7d4ea86ba4758e1ea82864c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java
@@ -216,7 +216,7 @@ public class ThemeUtil {
         @ColorInt
         public int colorAccent;
 
-        @AutoColor(R.attr.colorAccentFocus)
+        @AutoColor(R.attr.colorControlHighlight)
         @ColorInt
         public int colorAccentFocus;
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..5255927c1bc17bee418bffd610c9f87e92ae7268
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundActivity.java
@@ -0,0 +1,105 @@
+/*
+ * 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.util;
+
+import android.content.ComponentName;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+
+import de.kuschku.libquassel.BusProvider;
+import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread;
+import de.kuschku.quasseldroid_ng.service.QuasselService;
+import de.kuschku.quasseldroid_ng.ui.chat.Settings;
+import de.kuschku.quasseldroid_ng.ui.chat.util.ServiceHelper;
+import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+import de.kuschku.quasseldroid_ng.util.accounts.Account;
+
+public abstract class BoundActivity extends AppCompatActivity {
+    private QuasselService.LocalBinder binder;
+
+    private ServiceConnection connection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (service instanceof QuasselService.LocalBinder) {
+                binder = (QuasselService.LocalBinder) service;
+                binder.addCallback(BoundActivity.this::onConnectToThread);
+                onConnectToThread(binder.getBackgroundThread());
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            binder = null;
+            onConnectToThread(null);
+        }
+    };
+
+    protected AppContext context = new AppContext();
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        ServiceHelper.initTheme(context, this);
+        context.withSettings(new Settings(this));
+        context.settings().theme.addChangeListener(s -> recreate());
+        super.onCreate(savedInstanceState);
+        ServiceHelper.startServiceIfNotRunning(this);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        ServiceHelper.connectToService(this, connection);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        ServiceHelper.disconnect(this, connection);
+    }
+
+    protected void connectToServer(Account account) {
+        BusProvider provider = new BusProvider();
+        binder.startBackgroundThread(provider, account.toAddress());
+    }
+
+    protected void onConnectToThread(@Nullable ClientBackgroundThread thread) {
+        if (thread == null) {
+            context.withClient(null);
+            setProvider(null);
+        } else {
+            context.withClient(thread.client().client);
+            setProvider(thread.client().provider);
+        }
+    }
+
+    protected void setProvider(BusProvider provider) {
+        BusProvider oldProvider = context.provider();
+        if (oldProvider != null)
+            oldProvider.event.unregister(this);
+        if (provider != null)
+            provider.event.registerSticky(this);
+        context.withProvider(provider);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundFragment.java
new file mode 100644
index 0000000000000000000000000000000000000000..bfa02e762cfebc1746ed2c996cd050549acb675a
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/BoundFragment.java
@@ -0,0 +1,104 @@
+/*
+ * 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.util;
+
+import android.content.ComponentName;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+
+import de.kuschku.libquassel.BusProvider;
+import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread;
+import de.kuschku.quasseldroid_ng.service.QuasselService;
+import de.kuschku.quasseldroid_ng.ui.chat.Settings;
+import de.kuschku.quasseldroid_ng.ui.chat.util.ServiceHelper;
+import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+import de.kuschku.quasseldroid_ng.util.accounts.Account;
+
+public abstract class BoundFragment extends Fragment {
+    private QuasselService.LocalBinder binder;
+
+    private ServiceConnection connection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (service instanceof QuasselService.LocalBinder) {
+                binder = (QuasselService.LocalBinder) service;
+                binder.addCallback(BoundFragment.this::onConnectToThread);
+                onConnectToThread(binder.getBackgroundThread());
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            binder = null;
+            onConnectToThread(null);
+        }
+    };
+
+    protected AppContext context = new AppContext();
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        ServiceHelper.initTheme(context, getActivity());
+        context.withSettings(new Settings(getActivity()));
+        super.onCreate(savedInstanceState);
+        ServiceHelper.startServiceIfNotRunning(getContext());
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        ServiceHelper.connectToService(getContext(), connection);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        ServiceHelper.disconnect(getContext(), connection);
+    }
+
+    protected void connectToServer(Account account) {
+        BusProvider provider = new BusProvider();
+        binder.startBackgroundThread(provider, account.toAddress());
+    }
+
+    protected void onConnectToThread(@Nullable ClientBackgroundThread thread) {
+        if (thread == null) {
+            context.withClient(null);
+            setProvider(null);
+        } else {
+            context.withClient(thread.client().client);
+            setProvider(thread.client().provider);
+        }
+    }
+
+    protected void setProvider(BusProvider provider) {
+        BusProvider oldProvider = context.provider();
+        if (oldProvider != null)
+            oldProvider.event.unregister(this);
+        if (provider != null)
+            provider.event.registerSticky(this);
+        context.withProvider(provider);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/Account.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/Account.java
new file mode 100644
index 0000000000000000000000000000000000000000..85601c9b8053d64f8f2345c8e0f4c8eb2c40ad86
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/Account.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util.accounts;
+
+import java.util.UUID;
+
+import de.kuschku.util.ServerAddress;
+
+public class Account {
+    public final UUID id;
+
+    public final String name;
+
+    public final String host;
+    public final int port;
+
+    public final String user;
+    public final String pass;
+
+    public Account(UUID id, String name, String host, int port, String user, String pass) {
+        this.id = id;
+        this.name = name;
+        this.host = host;
+        this.port = port;
+        this.user = user;
+        this.pass = pass;
+    }
+
+    public ServerAddress toAddress() {
+        return new ServerAddress(host, port);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManager.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..5aa436af0651bf6febc984c2ab65ef1878d37baf
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManager.java
@@ -0,0 +1,61 @@
+/*
+ * 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.util.accounts;
+
+import android.content.Context;
+
+import java.util.Set;
+import java.util.UUID;
+
+import aspm.StringPreference;
+
+public class AccountManager {
+    AccountManagerHelper helper;
+
+    public AccountManager(Context context) {
+        helper = new AccountManagerHelper(context);
+    }
+
+    public Set<Account> accounts() {
+        return helper.findAllAccounts();
+    }
+
+    public void add(Account account) {
+        helper.addAccount(account);
+    }
+
+    public void remove(String id) {
+        remove(UUID.fromString(id));
+    }
+
+    public void remove(UUID id) {
+        helper.removeAccount(id);
+    }
+
+    public void remove(Account account) {
+        remove(account.id);
+    }
+
+    public Account account(String id) {
+        return helper.account(id);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManagerHelper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManagerHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ffc8f7b52ebf5f4850964e03ebd0c6cebfc0907
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/accounts/AccountManagerHelper.java
@@ -0,0 +1,203 @@
+/*
+ * 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.util.accounts;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteStatement;
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+public class AccountManagerHelper extends SQLiteOpenHelper {
+    private static final int DATABASE_VERSION = 1;
+    @NonNull
+    private static final String DATABASE_NAME = "accounts";
+    @NonNull
+    private static final String TABLE_ACCOUNTS = "accounts";
+
+    @NonNull
+    private static final String KEY_ID = "account_id";
+    @NonNull
+    private static final String KEY_NAME = "account_name";
+    @NonNull
+    private static final String KEY_HOST = "account_host";
+    @NonNull
+    private static final String KEY_PORT = "account_port";
+    @NonNull
+    private static final String KEY_USER = "account_user";
+    @NonNull
+    private static final String KEY_PASS = "account_pass";
+
+    // Again we can only use String.format, as SQL doesn’t support table or column names to be bound
+    // in prepared statements
+    @NonNull
+    private static final String STATEMENT_INSERT =
+            String.format("INSERT OR IGNORE INTO %s(%s, %s, %s, %s, %s, %s) VALUES (?, ?, ?, ?, ?, ?)",
+                    TABLE_ACCOUNTS, KEY_ID, KEY_NAME, KEY_HOST, KEY_PORT, KEY_USER, KEY_PASS);
+    @NonNull
+    private static final String STATEMENT_DELETE =
+            String.format("DELETE FROM %s WHERE %s = ?",
+                    TABLE_ACCOUNTS, KEY_ID);
+
+    @NonNull
+    private static final String SPECIFIER_FIND =
+            String.format("%s = ?", KEY_ID);
+
+    public AccountManagerHelper(Context context) {
+        super(context, DATABASE_NAME, null, DATABASE_VERSION);
+    }
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        // Why do we use String.format and not prepared statements? Because we can’t bind table or
+        // column names in prepared statements
+        String statement = String.format("CREATE TABLE %s (%s, %s, %s, %s, %s, %s, PRIMARY KEY (%s), UNIQUE(%s));",
+                TABLE_ACCOUNTS,
+                KEY_ID, KEY_NAME, KEY_HOST, KEY_PORT, KEY_USER, KEY_PASS,
+                KEY_ID,
+                KEY_ID);
+        db.execSQL(statement);
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+
+    }
+
+    public boolean addAccount(Account account) {
+        SQLiteDatabase db = this.getWritableDatabase();
+        SQLiteStatement statement = db.compileStatement(STATEMENT_INSERT);
+        statement.bindString(1, account.id.toString());
+        statement.bindString(2, account.name);
+        statement.bindString(3, account.host);
+        statement.bindLong(4, account.port);
+        statement.bindString(5, account.user);
+        statement.bindString(6, account.pass);
+        // executeInsert returns -1 if unsuccessful
+        return statement.executeInsert() != -1;
+    }
+
+    public boolean removeAccount(UUID id) {
+        return removeAccount(id.toString());
+    }
+
+    public boolean removeAccount(String id) {
+        SQLiteDatabase db = this.getWritableDatabase();
+        SQLiteStatement statement = db.compileStatement(STATEMENT_DELETE);
+        statement.bindString(1, id);
+        // executeUpdateDelete returns amount of modified rows
+        return statement.executeUpdateDelete() > 0;
+    }
+
+    private Cursor cursorFindAllAccounts() {
+        SQLiteDatabase db = this.getReadableDatabase();
+        return db.query(
+                // table name
+                TABLE_ACCOUNTS,
+                // column names
+                new String[]{KEY_ID, KEY_NAME, KEY_HOST, KEY_PORT, KEY_USER, KEY_PASS},
+                null,
+                null,
+                null,
+                null,
+                null,
+                null
+        );
+    }
+
+    private Cursor cursorFindAccount(String id) {
+        SQLiteDatabase db = this.getReadableDatabase();
+        return db.query(
+                // table name
+                TABLE_ACCOUNTS,
+                // column names
+                new String[]{KEY_ID, KEY_NAME, KEY_HOST, KEY_PORT, KEY_USER, KEY_PASS},
+                // where clause
+                SPECIFIER_FIND,
+                // binds for where clause
+                new String[]{id},
+                null,
+                null,
+                null,
+                null
+        );
+    }
+
+    @NonNull
+    public Set<Account> findAllAccounts() {
+        Cursor cursor = cursorFindAllAccounts();
+
+        Set<Account> accounts = new HashSet<>(cursor.getCount());
+
+        if (cursor.moveToFirst()) {
+            do {
+                String id = cursor.getString(0);
+                String name = cursor.getString(1);
+                String host = cursor.getString(2);
+                int port = (int) cursor.getLong(3);
+                String user = cursor.getString(4);
+                String pass = cursor.getString(5);
+                try {
+                    accounts.add(new Account(UUID.fromString(id), name, host, port, user, pass));
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    Log.e("AccountManager", "Removing account because invalid", e);
+                    removeAccount(id);
+                }
+            } while (cursor.moveToNext());
+        }
+
+        return accounts;
+    }
+
+    public Account account(String query_id) {
+        Cursor cursor = cursorFindAccount(query_id);
+
+        if (cursor.moveToFirst()) {
+            do {
+                String id = cursor.getString(0);
+                String name = cursor.getString(1);
+                String host = cursor.getString(2);
+                int port = (int) cursor.getLong(3);
+                String user = cursor.getString(4);
+                String pass = cursor.getString(5);
+                try {
+                    return new Account(UUID.fromString(id), name, host, port, user, pass);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    Log.e("AccountManager", "Removing account because invalid", e);
+                    removeAccount(id);
+                }
+            } while (cursor.moveToNext());
+        }
+
+        return null;
+    }
+}
diff --git a/app/src/main/java/de/kuschku/util/irc/IrcFormatHelper.java b/app/src/main/java/de/kuschku/util/irc/IrcFormatHelper.java
index ad9999231d6afcf1155c21800dd1ff5ef344766c..b538a376f0002c500edec378c800d313489ae38f 100644
--- a/app/src/main/java/de/kuschku/util/irc/IrcFormatHelper.java
+++ b/app/src/main/java/de/kuschku/util/irc/IrcFormatHelper.java
@@ -22,6 +22,7 @@
 package de.kuschku.util.irc;
 
 
+import android.app.Activity;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b5751ba8a0b579af4980c9bbbbe591d8ec0171ed
--- /dev/null
+++ b/app/src/main/res/anim/slide_in_right.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate android:fromXDelta="50%p" android:toXDelta="0"
+        android:duration="@android:integer/config_mediumAnimTime"/>
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:duration="@android:integer/config_mediumAnimTime" />
+</set>
diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3d7278e5f54763231d2731de3157da47c1297578
--- /dev/null
+++ b/app/src/main/res/anim/slide_out_left.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate android:fromXDelta="0" android:toXDelta="-50%p"
+        android:duration="@android:integer/config_mediumAnimTime"/>
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+        android:duration="@android:integer/config_mediumAnimTime" />
+</set>
+
diff --git a/app/src/main/res/color/selectable_button_background.xml b/app/src/main/res/color/selectable_button_background.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b14317e104f7cfcd02ed449ca06fc57a4aa1b8fa
--- /dev/null
+++ b/app/src/main/res/color/selectable_button_background.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_focused="true"  android:state_enabled="false" android:state_pressed="true" android:color="#8A777777" />
+    <item android:state_focused="true"  android:state_enabled="false"                              android:color="#8A777777" />
+    <item android:state_focused="true"                                android:state_pressed="true" android:color="#8A333333" />
+    <item android:state_focused="false"                               android:state_pressed="true" android:color="#83333333" />
+    <item android:state_focused="true"                                                             android:color="#8A333333" />
+    <item                                                                                          android:color="#8A000000" />
+</selector>
diff --git a/app/src/main/res/drawable-hdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-hdpi/ic_arrow_right_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..b0d7b5de459915e9495a781693cf1e88d653644f
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_arrow_right_dark.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-hdpi/ic_arrow_right_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..65248d20b30ebc08bdaae70baf78c9d02fc8a43f
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_arrow_right_light.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_check_dark.png b/app/src/main/res/drawable-hdpi/ic_check_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..6adfa198b63624fae6de340de17ea5e8b8a4a61e
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_check_dark.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_check_light.png b/app/src/main/res/drawable-hdpi/ic_check_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e4a0b2b345fd838bf05b06ab39910b58a2131a0
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_check_light.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_filter_dark.png b/app/src/main/res/drawable-hdpi/ic_filter_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd32743d1373bceb23abe67682c6e32e90f85050
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_filter_dark.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_filter_light.png b/app/src/main/res/drawable-hdpi/ic_filter_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..f0d8398f255f0ed47c5870e6c5d7862d43dbc4c9
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_filter_light.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_plus_light.png b/app/src/main/res/drawable-hdpi/ic_plus_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a4cd64e14ea8766c8177043517452442fd96fab
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_plus_light.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-mdpi/ic_arrow_right_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e98cc7508e3ab33d0c8e80ee40509eaf9ad33d7
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_arrow_right_dark.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-mdpi/ic_arrow_right_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..dd79fff4ab4f7f2f9cdc07ef80cd01255b0531f5
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_arrow_right_light.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_check_dark.png b/app/src/main/res/drawable-mdpi/ic_check_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..7298777f18e359b6ada165c7d3ced70e22b4b695
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_check_dark.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_check_light.png b/app/src/main/res/drawable-mdpi/ic_check_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ea8af1fe97bea31625ec101aba650bac33d1d21
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_check_light.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_filter_dark.png b/app/src/main/res/drawable-mdpi/ic_filter_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..ca32e41de952b2a2131e2fdac992b4598cd58e25
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_filter_dark.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_filter_light.png b/app/src/main/res/drawable-mdpi/ic_filter_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..41160593a9b8752613e16fe4e073052eadc33f65
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_filter_light.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_plus_light.png b/app/src/main/res/drawable-mdpi/ic_plus_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc3fd7e379c9db3583f17af658cb0413fe6bccab
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_plus_light.png differ
diff --git a/app/src/main/res/drawable-nodpi/bg.png b/app/src/main/res/drawable-nodpi/bg1.png
similarity index 100%
rename from app/src/main/res/drawable-nodpi/bg.png
rename to app/src/main/res/drawable-nodpi/bg1.png
diff --git a/app/src/main/res/drawable-nodpi/bg2.jpg~ b/app/src/main/res/drawable-nodpi/bg2.jpg~
new file mode 100644
index 0000000000000000000000000000000000000000..d55595ae5a8581e48647b76cd641524359cd2684
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/bg2.jpg~ differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-xhdpi/ic_arrow_right_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..0463e5cecfcc9b2561a359f689808c3aa6f65e4c
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_arrow_right_dark.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-xhdpi/ic_arrow_right_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..d2fd86fad0fd9c32a64cb24a45e164567f9e858a
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_arrow_right_light.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_check_dark.png b/app/src/main/res/drawable-xhdpi/ic_check_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..4eb240b352597fe8b8363b7adf64e8029bb2d01e
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_check_dark.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_check_light.png b/app/src/main/res/drawable-xhdpi/ic_check_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f9b108fc05fe842db406ee6f716e25895a8edcc
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_check_light.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_filter_dark.png b/app/src/main/res/drawable-xhdpi/ic_filter_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..0bf7bd655ac6930741df031f3d6e576cf4890025
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_filter_dark.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_filter_light.png b/app/src/main/res/drawable-xhdpi/ic_filter_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..f2ac8e1dada9f09656facb872716029a865b0db0
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_filter_light.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_plus_light.png b/app/src/main/res/drawable-xhdpi/ic_plus_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..949186c670f5bcd3c5c6c3c31c0b91b9352e296c
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_plus_light.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-xxhdpi/ic_arrow_right_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..770d53315bec425a36eb7d0e775d81bed1be6904
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_arrow_right_dark.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-xxhdpi/ic_arrow_right_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..7f3a9f19a5e6b14e1199d80879bd538e86eee454
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_arrow_right_light.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_check_dark.png b/app/src/main/res/drawable-xxhdpi/ic_check_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..c6503fd09eaf4ad9becd2c1a77f5bfdbd1d0b7be
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_check_dark.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_check_light.png b/app/src/main/res/drawable-xxhdpi/ic_check_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..392a259e9b36d8967c100c3e9084cb4ca8d83970
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_check_light.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_filter_dark.png b/app/src/main/res/drawable-xxhdpi/ic_filter_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..ade17c6a028e9d35cca3ab3a0e7054a582f21fc7
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_filter_dark.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_filter_light.png b/app/src/main/res/drawable-xxhdpi/ic_filter_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..06a23dce33ad8de6f6d4d42df9ac1199b8199684
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_filter_light.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_plus_light.png b/app/src/main/res/drawable-xxhdpi/ic_plus_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..4adbd6d374cb9efb879c5e3cbe557bb8e704749e
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_plus_light.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_dark.png b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..a2b73aa6909edd82c9ff5cbf21addbd2f2f244bb
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_dark.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_light.png b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..fd116d1c8f87db1bcae194ca144edbc77d351dc4
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right_light.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_check_dark.png b/app/src/main/res/drawable-xxxhdpi/ic_check_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..c297f32dd45f46a030b0acd9548eb7382508f385
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_check_dark.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_check_light.png b/app/src/main/res/drawable-xxxhdpi/ic_check_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..3400099ded2933bd1a070705ab4981c39aebea06
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_check_light.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_filter_dark.png b/app/src/main/res/drawable-xxxhdpi/ic_filter_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..c54b2eda6c8ecb52b215dabc28d5dddfae6bdba3
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_filter_dark.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_filter_light.png b/app/src/main/res/drawable-xxxhdpi/ic_filter_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..f70a17b53ee2637a1db7200071d7a143b27f34cb
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_filter_light.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_plus_light.png b/app/src/main/res/drawable-xxxhdpi/ic_plus_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..a5464a4b491d6522d5911f2ed293278ebb04792d
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_plus_light.png differ
diff --git a/app/src/main/res/layout-sw600dp-land/activity_setup.xml b/app/src/main/res/layout-sw600dp-land/activity_setup.xml
new file mode 100644
index 0000000000000000000000000000000000000000..76a3e2ed02d104400f56ba090300250a09c557b2
--- /dev/null
+++ b/app/src/main/res/layout-sw600dp-land/activity_setup.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<FrameLayout
+    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:background="?attr/colorPrimary">
+
+    <android.support.v4.view.ViewPager
+        android:id="@+id/view_pager"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <android.support.design.widget.FloatingActionButton
+        android:id="@+id/btn"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_arrow_right_dark"
+        android:layout_gravity="end|bottom"
+        android:layout_marginRight="80dp"
+        android:layout_marginEnd="80dp"
+        android:layout_marginBottom="16dp"
+        app:elevation="0dip"
+        app:backgroundTint="#8A000000"
+        app:fabSize="normal"/>
+
+</FrameLayout>
diff --git a/app/src/main/res/layout-sw600dp-land/slide.xml b/app/src/main/res/layout-sw600dp-land/slide.xml
new file mode 100644
index 0000000000000000000000000000000000000000..27cd43569626ff7cb33a4c7f0685c8b6685a3277
--- /dev/null
+++ b/app/src/main/res/layout-sw600dp-land/slide.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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/>.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="64dp"
+    android:paddingRight="64dp">
+
+    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/slideAccountcoreTitle"
+        android:textColor="@android:color/white"
+        android:textSize="28sp"
+        android:textStyle="bold"
+        android:layout_above="@+id/view"
+        android:layout_toLeftOf="@+id/scrollView2"
+        android:layout_toStartOf="@+id/scrollView2"
+        android:gravity="end"
+        android:paddingRight="64dp"
+        android:paddingEnd="64dp" />
+
+    <android.support.v4.widget.Space
+        android:layout_width="match_parent"
+        android:layout_height="32dp"
+        android:layout_centerVertical="true"
+        android:layout_toLeftOf="@+id/scrollView2"
+        android:layout_toStartOf="@+id/scrollView2"
+        android:id="@+id/view" />
+
+    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/description"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/slideAccountcoreDescription"
+        android:textColor="@android:color/white"
+        android:textSize="16sp"
+        android:layout_below="@+id/view"
+        android:layout_toLeftOf="@+id/scrollView2"
+        android:layout_toStartOf="@+id/scrollView2"
+        android:gravity="end"
+        android:paddingRight="64dp"
+        android:paddingEnd="64dp" />
+
+    <ScrollView
+        android:id="@+id/scrollView2"
+        android:layout_width="400dp"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentEnd="true">
+
+        <android.support.v7.widget.CardView
+            android:id="@+id/content_host"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:minHeight="400dp"
+            android:background="@color/md_light_background" />
+
+    </ScrollView>
+
+</RelativeLayout>
diff --git a/app/src/main/res/layout-sw600dp/activity_setup.xml b/app/src/main/res/layout-sw600dp/activity_setup.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e00fb748f1c1e1cf5677c3d4e06321338fecf655
--- /dev/null
+++ b/app/src/main/res/layout-sw600dp/activity_setup.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<FrameLayout
+    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:background="?attr/colorPrimary">
+
+    <android.support.v4.view.ViewPager
+        android:id="@+id/view_pager"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <FrameLayout
+        android:layout_width="400dp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|center">
+
+        <android.support.design.widget.FloatingActionButton
+            android:id="@+id/btn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/ic_arrow_right_dark"
+            android:layout_gravity="end|bottom"
+            android:layout_marginRight="16dp"
+            android:layout_marginEnd="16dp"
+            android:layout_marginBottom="16dp"
+            app:elevation="0dip"
+            app:backgroundTint="#8A000000"
+            app:fabSize="normal" />
+
+    </FrameLayout>
+
+</FrameLayout>
diff --git a/app/src/main/res/layout-sw600dp/slide.xml b/app/src/main/res/layout-sw600dp/slide.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e23f40b3856675418134039a281ca55eb20774b4
--- /dev/null
+++ b/app/src/main/res/layout-sw600dp/slide.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent">
+
+    <ScrollView
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_gravity="bottom">
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="400dp"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="64dp"
+                android:padding="32dp"
+                android:orientation="vertical">
+
+                <TextView
+                    xmlns:android="http://schemas.android.com/apk/res/android"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:textStyle="bold"
+                    android:textColor="@android:color/white"
+                    android:textSize="28sp"
+                    android:layout_marginBottom="32dp"
+                    android:text="@string/slideAccountcoreTitle"
+                    android:id="@+id/title" />
+
+                <TextView
+                    xmlns:android="http://schemas.android.com/apk/res/android"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:textColor="@android:color/white"
+                    android:textSize="16sp"
+                    android:text="@string/slideAccountcoreDescription"
+                    android:id="@+id/description" />
+
+            </LinearLayout>
+
+            <android.support.v7.widget.CardView
+                android:id="@+id/content_host"
+                android:minHeight="400dp"
+                android:background="@color/md_light_background"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</FrameLayout>
diff --git a/app/src/main/res/layout-w720dp/activity_main.xml b/app/src/main/res/layout-w720dp/activity_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2193aacb69d546053146a73c289d7c335ab63c9f
--- /dev/null
+++ b/app/src/main/res/layout-w720dp/activity_main.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".ui.chat.MainActivity">
+
+    <FrameLayout
+        android:id="@+id/drawer_host"
+        android:layout_width="300dp"
+        android:layout_height="match_parent" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <include layout="@layout/widget_actionbar" />
+
+        <FrameLayout
+            android:id="@+id/content_host"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+    </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_accountchooser.xml b/app/src/main/res/layout/activity_accountchooser.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d47d053c3359e3723e986f664708f791fec2679d
--- /dev/null
+++ b/app/src/main/res/layout/activity_accountchooser.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml
index 3ccfa08ec1ab58135896bede244578fa213f4adc..50b28109bf9a1412377fd487091ac6b5d1a251b0 100644
--- a/app/src/main/res/layout/activity_chat.xml
+++ b/app/src/main/res/layout/activity_chat.xml
@@ -26,7 +26,7 @@
     android:layout_height="match_parent"
     android:orientation="vertical">
 
-    <include layout="@layout/toolbar" />
+    <include layout="@layout/widget_actionbar" />
 
     <com.sothree.slidinguppanel.SlidingUpPanelLayout
         android:id="@+id/sliding_layout"
@@ -38,9 +38,9 @@
         app:umanoScrollableView="@+id/chatline_scroller"
         app:umanoShadowHeight="4dp">
 
-        <include layout="@layout/content_main" />
+        <include layout="@layout/fragment_chat" />
 
-        <include layout="@layout/slider_main" />
+        <include layout="@layout/widget_slider" />
 
     </com.sothree.slidinguppanel.SlidingUpPanelLayout>
 
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/activity_main.xml
similarity index 72%
rename from app/src/main/res/layout/content_main.xml
rename to app/src/main/res/layout/activity_main.xml
index e5ab0fb3d7e971b0c693e98726229c2d4cc93246..50c6366d12737caaaec9bd999ccbf2bd37b177c8 100644
--- a/app/src/main/res/layout/content_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -20,17 +20,19 @@
   ~ with this program.  If not, see <http://www.gnu.org/licenses/>.
   -->
 
-<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/swipe_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="?attr/colorBackground"
-    tools:showIn="@layout/activity_chat">
+    android:orientation="vertical"
+    tools:context=".ui.chat.MainActivity">
 
-    <android.support.v7.widget.RecyclerView
-        android:id="@+id/messages"
+    <include layout="@layout/widget_actionbar" />
+
+    <FrameLayout
+        android:id="@+id/content_host"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:clickable="true" />
-</android.support.v4.widget.SwipeRefreshLayout>
+        android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_setup.xml b/app/src/main/res/layout/activity_setup.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c8168d03a062b5041646cde1e3caff7d2342f3e6
--- /dev/null
+++ b/app/src/main/res/layout/activity_setup.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<FrameLayout
+    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:background="?attr/colorPrimary">
+
+    <android.support.v4.view.ViewPager
+        android:id="@+id/view_pager"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <android.support.design.widget.FloatingActionButton
+        android:id="@+id/btn"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_arrow_right_dark"
+        android:layout_gravity="end|bottom"
+        android:layout_marginRight="16dp"
+        android:layout_marginEnd="16dp"
+        android:layout_marginBottom="16dp"
+        app:elevation="0dip"
+        app:backgroundTint="#8A000000"
+        app:fabSize="normal" />
+
+</FrameLayout>
diff --git a/app/src/main/res/layout/fragment_chat.xml b/app/src/main/res/layout/fragment_chat.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a38ddea7544ad89dcd418f1e61f8afa0c8a94433
--- /dev/null
+++ b/app/src/main/res/layout/fragment_chat.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<com.sothree.slidinguppanel.SlidingUpPanelLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/sliding_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="bottom"
+    android:orientation="vertical"
+    app:umanoPanelHeight="?attr/actionBarSize"
+    app:umanoScrollableView="@+id/chatline_scroller"
+    app:umanoShadowHeight="4dp"
+    android:background="?attr/colorBackground"
+    tools:showIn="@layout/activity_chat">
+
+    <android.support.v4.widget.SwipeRefreshLayout
+        android:id="@+id/swipe_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <android.support.v7.widget.RecyclerView
+            android:id="@+id/messages"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:clickable="true" />
+    </android.support.v4.widget.SwipeRefreshLayout>
+
+    <include layout="@layout/widget_slider" />
+
+</com.sothree.slidinguppanel.SlidingUpPanelLayout>
diff --git a/app/src/main/res/layout/fragment_loading.xml b/app/src/main/res/layout/fragment_loading.xml
new file mode 100644
index 0000000000000000000000000000000000000000..997f5c18faa1dd1cd87c21cff128ff46570659c6
--- /dev/null
+++ b/app/src/main/res/layout/fragment_loading.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="?attr/colorBackground">
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="240dp"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_centerHorizontal="true">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+            <TextView
+                android:layout_width="0dip"
+                android:layout_weight="1"
+                android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.AppCompat.Caption"
+                android:text="Connecting"
+                android:id="@+id/label" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.AppCompat.Caption"
+                android:text="1/15"
+                android:id="@+id/count" />
+        </LinearLayout>
+        <ProgressBar
+            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:indeterminate="true"
+            android:id="@+id/progressBar" />
+    </LinearLayout>
+</RelativeLayout>
diff --git a/app/src/main/res/layout/slide.xml b/app/src/main/res/layout/slide.xml
new file mode 100644
index 0000000000000000000000000000000000000000..884a2531142bfe69d3b964c1478f7a1ba57c5401
--- /dev/null
+++ b/app/src/main/res/layout/slide.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent">
+
+    <ScrollView
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_gravity="bottom">
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="96dp"
+                android:padding="32dp"
+                android:orientation="vertical">
+
+                <TextView
+                    xmlns:android="http://schemas.android.com/apk/res/android"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:textStyle="bold"
+                    android:textColor="@android:color/white"
+                    android:textSize="28sp"
+                    android:layout_marginBottom="32dp"
+                    android:text="@string/slideAccountcoreTitle"
+                    android:id="@+id/title" />
+
+                <TextView
+                    xmlns:android="http://schemas.android.com/apk/res/android"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:textColor="@android:color/white"
+                    android:textSize="16sp"
+                    android:text="@string/slideAccountcoreDescription"
+                    android:id="@+id/description" />
+
+            </LinearLayout>
+
+            <android.support.v7.widget.CardView
+                android:id="@+id/content_host"
+                android:minHeight="240dp"
+                android:background="@color/md_light_background"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</FrameLayout>
diff --git a/app/src/main/res/layout/slide_account_core.xml b/app/src/main/res/layout/slide_account_core.xml
new file mode 100644
index 0000000000000000000000000000000000000000..de5791d490fa396ceb37395672f46843bae32386
--- /dev/null
+++ b/app/src/main/res/layout/slide_account_core.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="32dp">
+
+    <android.support.design.widget.TextInputLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="Hostname">
+        <android.support.v7.widget.AppCompatEditText
+            android:id="@+id/host"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="textUri" />
+    </android.support.design.widget.TextInputLayout>
+
+    <android.support.design.widget.TextInputLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="Port">
+        <android.support.v7.widget.AppCompatEditText
+            android:id="@+id/port"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="number" />
+    </android.support.design.widget.TextInputLayout>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/slide_account_name.xml b/app/src/main/res/layout/slide_account_name.xml
new file mode 100644
index 0000000000000000000000000000000000000000..49c8e4a5a240026ab637badd2cbab6be293413a9
--- /dev/null
+++ b/app/src/main/res/layout/slide_account_name.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="32dp">
+
+    <android.support.design.widget.TextInputLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="Account Name">
+        <android.support.v7.widget.AppCompatEditText
+            android:id="@+id/name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="textEmailSubject" />
+    </android.support.design.widget.TextInputLayout>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/slide_account_user.xml b/app/src/main/res/layout/slide_account_user.xml
new file mode 100644
index 0000000000000000000000000000000000000000..88a9fcba80ed8ab193858c05626a089b8542ec54
--- /dev/null
+++ b/app/src/main/res/layout/slide_account_user.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="32dp">
+
+    <android.support.design.widget.TextInputLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="Username">
+        <android.support.v7.widget.AppCompatEditText
+            android:id="@+id/user"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="textVisiblePassword" />
+    </android.support.design.widget.TextInputLayout>
+
+    <android.support.design.widget.TextInputLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="Password">
+        <android.support.v7.widget.AppCompatEditText
+            android:id="@+id/pass"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="textPassword" />
+    </android.support.design.widget.TextInputLayout>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/slide_select.xml b/app/src/main/res/layout/slide_select.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9cd2f7aa6b8cde3d0acf9f822a39def3a54d3256
--- /dev/null
+++ b/app/src/main/res/layout/slide_select.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<android.support.v7.widget.RecyclerView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="400dp" />
diff --git a/app/src/main/res/layout/toolbar.xml b/app/src/main/res/layout/widget_actionbar.xml
similarity index 100%
rename from app/src/main/res/layout/toolbar.xml
rename to app/src/main/res/layout/widget_actionbar.xml
diff --git a/app/src/main/res/layout/widget_core_account.xml b/app/src/main/res/layout/widget_core_account.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1705a7400a23a8f5db92423eb244c713b2e146d5
--- /dev/null
+++ b/app/src/main/res/layout/widget_core_account.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/material_drawer_item_profile"
+    android:orientation="horizontal"
+    android:paddingEnd="@dimen/material_drawer_vertical_padding"
+    android:paddingLeft="@dimen/material_drawer_vertical_padding"
+    android:paddingRight="@dimen/material_drawer_vertical_padding"
+    android:paddingStart="@dimen/material_drawer_vertical_padding">
+
+    <LinearLayout
+        android:layout_width="@dimen/material_drawer_item_profile_icon_width"
+        android:layout_height="@dimen/material_drawer_item_profile"
+        android:paddingBottom="@dimen/material_drawer_item_profile_icon_padding"
+        android:paddingEnd="@dimen/material_drawer_item_profile_icon_padding_right"
+        android:paddingLeft="0dp"
+        android:paddingRight="@dimen/material_drawer_item_profile_icon_padding_right"
+        android:paddingStart="0dp"
+        android:paddingTop="@dimen/material_drawer_item_profile_icon_padding">
+
+        <android.support.v7.widget.AppCompatRadioButton
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:id="@+id/account_select" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical|start"
+        android:orientation="vertical"
+        android:paddingEnd="0dp"
+        android:paddingLeft="@dimen/material_drawer_padding"
+        android:paddingRight="0dp"
+        android:paddingStart="@dimen/material_drawer_padding">
+
+        <TextView
+            android:id="@+id/account_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:fontFamily="sans-serif-medium"
+            android:gravity="center_vertical|start"
+            android:lines="1"
+            android:paddingRight="@dimen/material_drawer_item_primary_icon_padding_right"
+            android:singleLine="true"
+            android:textDirection="anyRtl"
+            android:textSize="@dimen/material_drawer_item_profile_text"
+            tools:text="Remote" />
+
+        <TextView
+            android:id="@+id/account_description"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:fontFamily="sans-serif"
+            android:gravity="center_vertical|start"
+            android:lines="1"
+            android:singleLine="true"
+            android:textDirection="anyRtl"
+            android:textSize="@dimen/material_drawer_item_profile_description"
+            tools:text="kuschku on kuschku.de" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/widget_core_account_add.xml b/app/src/main/res/layout/widget_core_account_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..52382d73349b892fcd6cab188b0cd6451caedf26
--- /dev/null
+++ b/app/src/main/res/layout/widget_core_account_add.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/material_drawer_item_profile"
+    android:orientation="horizontal"
+    android:paddingEnd="@dimen/material_drawer_vertical_padding"
+    android:paddingLeft="@dimen/material_drawer_vertical_padding"
+    android:paddingRight="@dimen/material_drawer_vertical_padding"
+    android:paddingStart="@dimen/material_drawer_vertical_padding">
+
+    <LinearLayout
+        android:layout_width="@dimen/material_drawer_item_profile_icon_width"
+        android:layout_height="@dimen/material_drawer_item_profile"
+        android:paddingBottom="@dimen/material_drawer_item_profile_icon_padding"
+        android:paddingEnd="@dimen/material_drawer_item_profile_icon_padding_right"
+        android:paddingLeft="0dp"
+        android:paddingRight="@dimen/material_drawer_item_profile_icon_padding_right"
+        android:paddingStart="0dp"
+        android:paddingTop="@dimen/material_drawer_item_profile_icon_padding">
+
+        <ImageView
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_gravity="center_vertical"
+            android:src="@drawable/ic_plus_light" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical|start"
+        android:orientation="vertical"
+        android:paddingEnd="0dp"
+        android:paddingLeft="@dimen/material_drawer_padding"
+        android:paddingRight="0dp"
+        android:paddingStart="@dimen/material_drawer_padding">
+
+        <TextView
+            android:id="@+id/account_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:fontFamily="sans-serif-medium"
+            android:gravity="center_vertical|start"
+            android:lines="1"
+            android:paddingRight="@dimen/material_drawer_item_primary_icon_padding_right"
+            android:singleLine="true"
+            android:textDirection="anyRtl"
+            android:textSize="@dimen/material_drawer_item_profile_text"
+            android:text="Add Account" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/widget_editor.xml b/app/src/main/res/layout/widget_editor.xml
index 5031c7cbcd80de29fc0be0da5f202264424640ac..a41550b8df07ebd2f05270b02ac5cbe5fd47d6b6 100644
--- a/app/src/main/res/layout/widget_editor.xml
+++ b/app/src/main/res/layout/widget_editor.xml
@@ -24,8 +24,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:paddingBottom="@dimen/message_history_panel_height"
-    tools:showIn="@layout/slider_main">
+    tools:showIn="@layout/widget_slider">
 
     <ScrollView
         android:id="@+id/chatline_scroller"
diff --git a/app/src/main/res/layout/slider_main.xml b/app/src/main/res/layout/widget_slider.xml
similarity index 97%
rename from app/src/main/res/layout/slider_main.xml
rename to app/src/main/res/layout/widget_slider.xml
index a83f5d5b0fcfd18dd87f70ad9ec9e20f1ee757cf..e26f756b9359256fde15bc9d9aeb01e88c3e8f0c 100644
--- a/app/src/main/res/layout/slider_main.xml
+++ b/app/src/main/res/layout/widget_slider.xml
@@ -32,7 +32,7 @@
     android:gravity="bottom"
     sothree:umanoFadeColor="?attr/colorBackgroundCard"
     sothree:umanoOverlay="true"
-    sothree:umanoPanelHeight="@dimen/message_history_panel_height"
+    sothree:umanoPanelHeight="0dip"
     sothree:umanoScrollableView="@+id/msg_history"
     sothree:umanoShadowHeight="0.0dip"
     tools:showIn="@layout/activity_chat">
diff --git a/app/src/main/res/menu/chat.xml b/app/src/main/res/menu/chat.xml
index e5cbf8eae2cf96727e43514a581e8b51551215fa..5b232764cb900c0d3df9db7793606baabdd2a9ae 100644
--- a/app/src/main/res/menu/chat.xml
+++ b/app/src/main/res/menu/chat.xml
@@ -22,10 +22,14 @@
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item
+        android:id="@+id/action_reauth"
+        android:title="Reauth"
+        app:showAsAction="ifRoom" />
     <item
         android:id="@+id/action_hide_events"
-        android:icon="@android:drawable/ic_menu_sort_by_size"
+        android:icon="@drawable/ic_filter_dark"
         android:orderInCategory="100"
         android:title="@string/labelHideEvents"
-        app:showAsAction="never" />
+        app:showAsAction="ifRoom" />
 </menu>
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000000000000000000000000000000000000..24ea19facc5101226f994ef3483b970269489c88
--- /dev/null
+++ b/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<resources>
+    <style name="Base.SetupTheme" parent="Theme.AppCompat.Light.NoActionBar">
+        <item name="android:windowTranslucentStatus">true</item>
+    </style>
+</resources>
diff --git a/app/src/main/res/values-w720dp/bools.xml b/app/src/main/res/values-w720dp/bools.xml
new file mode 100644
index 0000000000000000000000000000000000000000..533e6f4eadfe231d29736242ea846d8b4253d44f
--- /dev/null
+++ b/app/src/main/res/values-w720dp/bools.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<resources>
+    <bool name="isTablet">true</bool>
+</resources>
diff --git a/app/src/main/res/values-w720dp/styles.xml b/app/src/main/res/values-w720dp/styles.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e822c3c732598c21402f9760623dab66f8412c48
--- /dev/null
+++ b/app/src/main/res/values-w720dp/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<resources>
+    <style name="BaseTheme" parent="MaterialDrawerTheme" />
+    <style name="BaseTheme.Light" parent="MaterialDrawerTheme.Light.DarkToolbar" />
+</resources>
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 986086c9dc4ce663a209e80369346c9584e057cb..5ab6942105e71f24bf78450946ae0c69553fcab0 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -21,8 +21,6 @@
   -->
 
 <resources>
-    <attr name="colorAccentFocus" />
-
     <!-- sender colors -->
 
     <attr name="senderColor0" format="color" />
@@ -88,6 +86,7 @@
     <attr name="iconFormatFill" format="reference" />
     <attr name="iconHistory" format="reference" />
     <attr name="iconDebug" format="reference" />
+    <attr name="iconFilter" format="reference" />
 
     <attr name="cardStyle" format="reference" />
 </resources>
diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml
new file mode 100644
index 0000000000000000000000000000000000000000..26d3877c3d5a22a85ccc4670105434059aa24fce
--- /dev/null
+++ b/app/src/main/res/values/bools.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<resources>
+    <bool name="isTablet">false</bool>
+</resources>
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index b0c2c55c9d87f134369b4efbe58fe847893cc44a..6594d1de52c7ba13099f531ac239953f5914155d 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -27,5 +27,5 @@
     <dimen name="message_horizontal">8dp</dimen>
     <dimen name="message_vertical">4dp</dimen>
 
-    <dimen name="message_history_panel_height">0dip</dimen>
+    <dimen name="circular_button_size">56dp</dimen>
 </resources>
diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml
index 49842553e87f668fdcf83134b704bee7fd60fc37..f5667ed02f62737dad37805116bf5cb501cd4094 100644
--- a/app/src/main/res/values/ids.xml
+++ b/app/src/main/res/values/ids.xml
@@ -23,4 +23,6 @@
 <resources>
     <item name="custom_url_span" type="id" />
     <item name="custom_channel_span" type="id" />
+    <item name="item_create_account" type="id" />
+    <item name="item_account" type="id" />
 </resources>
diff --git a/app/src/main/res/values/preferences.xml b/app/src/main/res/values/preferences.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d451c47cbed7a904c6d1e321092151f9f4ae2adb
--- /dev/null
+++ b/app/src/main/res/values/preferences.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<resources>
+    <string name="preference_theme" translatable="false">selectedtheme</string>
+    <string name="preference_theme_title">Theme</string>
+    <string-array name="preference_theme_entries">
+        <item>Google® Material (Light)</item>
+        <item>Google® Material (Dark)</item>
+        <item>Quassel™ (Light)</item>
+        <item>Quassel™ (Dark)</item>
+        <!--<item>Solarized (Light)</item>-->
+        <item>Solarized (Dark)</item>
+    </string-array>
+    <string-array name="preference_theme_values">
+        <item>MATERIAL_LIGHT</item>
+        <item>MATERIAL_DARK</item>
+        <item>QUASSEL_LIGHT</item>
+        <item>QUASSEL_DARK</item>
+        <!--<item>SOLARIZED_LIGHT</item>-->
+        <item>SOLARIZED_DARK</item>
+    </string-array>
+</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e9564f3292a120b083f76a7e38c8bb1c804fb9e8..80916c85a24ae0a775aea73f03eb037fdb05455d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -28,33 +28,6 @@
     <string name="appLinkCommunityTitle">Community</string>
     <string name="appLinkCommunityUrl" translatable="false">https://plus.google.com/communities/104094956084217666662</string>
 
-    <!-- Message format strings -->
-    <string name="usernameHostmask">%1$s (%2$s)</string>
-
-    <string name="messagePlain">%1$s: %2$s</string>
-
-    <string name="messageJoin">%1$s has joined %2$s</string>
-
-    <string name="messagePart">%1$s has left %2$s</string>
-    <string name="messagePartExtra">"%1$s has left %2$s (%3$s)</string>
-
-    <string name="messageQuit">%1$s has quit</string>
-    <string name="messageQuitExtra">%1$s has quit (%2$s)</string>
-
-    <string name="messageKill">%1$s was killed: %2$s</string>
-
-    <string name="messageKick">%1$s has kicked %2$s from %3$s</string>
-    <string name="messageKickExtra">%1$s has kicked %2$s from %3$s: %4$s</string>
-
-    <string name="messageMode">Mode %1$s by %2$s</string>
-
-    <string name="messageNickSelf">You are now known as %1$s</string>
-    <string name="messageNickOther">%1$s is now known as %2$s</string>
-
-    <string name="messageDayChange">{ Day changed to %1$s }</string>
-
-    <string name="messageAction">* %1$s %2$s</string>
-
     <!-- Editor UI -->
     <string name="placeholder">Write a message…</string>
     <string name="formatBold">Bold</string>
@@ -66,7 +39,7 @@
     <!-- Actions -->
     <string name="labelLogin">Login</string>
     <string name="labelCancel">Cancel</string>
-    <string name="labelConnect">Connect</string>
+    <string name="labelReconnect">Connect</string>
     <string name="labelSettings">Settings</string>
     <string name="labelStatusBuffer">Status Buffer</string>
     <string name="labelAddress">Address</string>
@@ -78,5 +51,18 @@
     <string name="labelHideEvents">Hide events</string>
 
     <string name="warningCertificate">Do you trust this certificate?</string>
-    <string name="labelDebug">Debug</string>
+
+    <string name="labelUserOnHost">%1$s on %2$s</string>
+
+    <string name="slideAccountcoreTitle">The Core</string>
+    <string name="slideAccountcoreDescription">First, please choose which server your core is hosted on – if you don’t know what a core is, click [here]</string>
+
+    <string name="slideAccountuserTitle">Your Account</string>
+    <string name="slideAccountuserDescription">Now, please enter the username and password for your account on the core. If you just created that core, we’ll set up this account for you</string>
+
+    <string name="slideAccountselectTitle">Select Account</string>
+    <string name="slideAccountselectDescription">Please select an account from the list or add one</string>
+
+    <string name="slideAccountnameTitle">Customize Account</string>
+    <string name="slideAccountnameDescription">Give this account a name and icon</string>
 </resources>
diff --git a/app/src/main/res/values/strings_format.xml b/app/src/main/res/values/strings_format.xml
new file mode 100644
index 0000000000000000000000000000000000000000..852d78f036ea0f1a41794883ba2aa124b1d24868
--- /dev/null
+++ b/app/src/main/res/values/strings_format.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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/>.
+  -->
+
+<resources>
+    <!-- Message format strings -->
+    <string name="usernameHostmask">%1$s (%2$s)</string>
+
+    <string name="messagePlain">%1$s: %2$s</string>
+
+    <string name="messageJoin">%1$s has joined %2$s</string>
+
+    <string name="messagePart">%1$s has left %2$s</string>
+    <string name="messagePartExtra">"%1$s has left %2$s (%3$s)</string>
+
+    <string name="messageQuit">%1$s has quit</string>
+    <string name="messageQuitExtra">%1$s has quit (%2$s)</string>
+
+    <string name="messageKill">%1$s was killed: %2$s</string>
+
+    <string name="messageKick">%1$s has kicked %2$s from %3$s</string>
+    <string name="messageKickExtra">%1$s has kicked %2$s from %3$s: %4$s</string>
+
+    <string name="messageMode">Mode %1$s by %2$s</string>
+
+    <string name="messageNickSelf">You are now known as %1$s</string>
+    <string name="messageNickOther">%1$s is now known as %2$s</string>
+
+    <string name="messageDayChange">{ Day changed to %1$s }</string>
+
+    <string name="messageAction">* %1$s %2$s</string>
+</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index d23e2803f43246c7af044316d53251491f86ab45..3ac174f46de126d95fb15e97458d43e4b721085a 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -20,17 +20,22 @@
   -->
 
 <resources>
+    <style name="BaseTheme" parent="MaterialDrawerTheme.TranslucentStatus" />
+    <style name="BaseTheme.Light" parent="MaterialDrawerTheme.Light.DarkToolbar.TranslucentStatus" />
 
     <!-- Base application theme. -->
-    <style name="AppTheme" parent="MaterialDrawerTheme.TranslucentStatus">
+    <style name="AppTheme" parent="BaseTheme">
         <!-- Customize your theme here. -->
         <item name="colorPrimary">@color/colorPrimary</item>
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
         <item name="colorAccent">@color/colorAccent</item>
-        <item name="colorAccentFocus">@color/colorAccentFocus</item>
-
         <item name="colorControlHighlight">@color/colorAccentFocus</item>
         <item name="windowActionModeOverlay">true</item>
+
+        <item name="material_drawer_background">?attr/colorBackground</item>
+        <item name="material_drawer_primary_text">?attr/colorForeground</item>
+        <item name="material_drawer_primary_icon">?attr/colorForeground</item>
+        <item name="material_drawer_secondary_text">?attr/colorForegroundSecondary</item>
         
         <item name="iconFormatBold">@drawable/ic_format_bold_dark</item>
         <item name="iconFormatItalic">@drawable/ic_format_italic_dark</item>
@@ -39,20 +44,24 @@
         <item name="iconFormatFill">@drawable/ic_format_fill_dark</item>
         <item name="iconHistory">@drawable/ic_history_dark</item>
         <item name="iconDebug">@drawable/ic_bug_dark</item>
+        <item name="iconFilter">@drawable/ic_filter_dark</item>
 
         <item name="cardStyle">@style/CardView.Dark</item>
     </style>
 
-    <style name="AppTheme.Light" parent="MaterialDrawerTheme.Light.DarkToolbar.TranslucentStatus">
+    <style name="AppTheme.Light" parent="BaseTheme.Light">
         <!-- Customize your theme here. -->
         <item name="colorPrimary">@color/colorPrimary</item>
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
         <item name="colorAccent">@color/colorAccent</item>
-        <item name="colorAccentFocus">@color/colorAccentFocus</item>
-
         <item name="colorControlHighlight">@color/colorAccentFocus</item>
         <item name="windowActionModeOverlay">true</item>
 
+        <item name="material_drawer_background">?attr/colorBackground</item>
+        <item name="material_drawer_primary_text">?attr/colorForeground</item>
+        <item name="material_drawer_primary_icon">?attr/colorForeground</item>
+        <item name="material_drawer_secondary_text">?attr/colorForegroundSecondary</item>
+
         <item name="iconFormatBold">@drawable/ic_format_bold_light</item>
         <item name="iconFormatItalic">@drawable/ic_format_italic_light</item>
         <item name="iconFormatUnderline">@drawable/ic_format_underline_light</item>
@@ -60,10 +69,22 @@
         <item name="iconFormatFill">@drawable/ic_format_fill_light</item>
         <item name="iconHistory">@drawable/ic_history_light</item>
         <item name="iconDebug">@drawable/ic_bug_light</item>
+        <item name="iconFilter">@drawable/ic_filter_light</item>
 
         <item name="cardStyle">@style/CardView.Light</item>
     </style>
 
+    <style name="Base.SetupTheme" parent="Theme.AppCompat.Light.NoActionBar" />
+
+    <style name="SetupTheme" parent="Theme.AppCompat.Light.NoActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+        <item name="colorControlHighlight">@color/colorAccentFocus</item>
+        <item name="windowActionModeOverlay">true</item>
+    </style>
+
     <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
 
     <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Dark" />
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 1805fe606cdf6b2ea4402c55e44667bfd0e0b247..ee979f7c7e542b6278c6fc406987368e0e5db7b2 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -220,4 +220,59 @@
         <item name="colorTintMessage">#2277dd</item>
         <item name="colorTintHighlight">#ff8811</item>
     </style>
+
+    <style name="Solarized_Dark" parent="AppTheme">
+        <item name="colorPrimary">?attr/colorBackgroundCard</item>
+        <item name="colorPrimaryDark">?attr/colorBackground</item>
+        <item name="colorAccent">#B58900</item>
+        <item name="colorControlHighlight">#40B58900</item>
+
+        <item name="senderColor0">#B58900</item>
+        <item name="senderColor1">#CB4B16</item>
+        <item name="senderColor2">#DC322f</item>
+        <item name="senderColor3">#D33682</item>
+        <item name="senderColor4">#6C71C4</item>
+        <item name="senderColor5">#268BD2</item>
+        <item name="senderColor6">#2AA198</item>
+        <item name="senderColor7">#859900</item>
+        <item name="senderColor8">#D5A920</item>
+        <item name="senderColor9">#EB6B36</item>
+        <item name="senderColorA">#FC524f</item>
+        <item name="senderColorB">#F356A2</item>
+        <item name="senderColorC">#8C91E4</item>
+        <item name="senderColorD">#46ABF2</item>
+        <item name="senderColorE">#4AC1B8</item>
+        <item name="senderColorF">#657900</item>
+
+        <item name="mircColor0">#ffffff</item>
+        <item name="mircColor1">#000000</item>
+        <item name="mircColor2">#1155aa</item>
+        <item name="mircColor3">#008000</item>
+        <item name="mircColor4">#ff0000</item>
+        <item name="mircColor5">#800000</item>
+        <item name="mircColor6">#800080</item>
+        <item name="mircColor7">#ffa500</item>
+        <item name="mircColor8">#ffff00</item>
+        <item name="mircColor9">#00ff00</item>
+        <item name="mircColorA">#008080</item>
+        <item name="mircColorB">#00ffff</item>
+        <item name="mircColorC">#1155ff</item>
+        <item name="mircColorD">#ff00ff</item>
+        <item name="mircColorE">#808080</item>
+        <item name="mircColorF">#c0c0c0</item>
+
+        <item name="colorForeground">#839495</item>
+        <item name="colorForegroundHighlight">#839495</item>
+        <item name="colorForegroundSecondary">#576A66</item>
+        <item name="colorForegroundAction">#268BD2</item>
+
+        <item name="colorBackground">#002B36</item>
+        <item name="colorBackgroundHighlight">#268bd2</item>
+        <item name="colorBackgroundSecondary">#073642</item>
+        <item name="colorBackgroundCard">#073642</item>
+
+        <item name="colorTintActivity">#88cc33</item>
+        <item name="colorTintMessage">#2277dd</item>
+        <item name="colorTintHighlight">#ff8811</item>
+    </style>
 </resources>
diff --git a/aspm b/aspm
deleted file mode 160000
index 9a6dc7fbbf275b54ab74a66a282769f63e9dc120..0000000000000000000000000000000000000000
--- a/aspm
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 9a6dc7fbbf275b54ab74a66a282769f63e9dc120
diff --git a/install.sh b/install.sh
index 0043c696996d74cf9c4a0f85bf9b1d63f65a6a2e..2f12876bcfdc848ef78ce6358a260c1489b1aeeb 100755
--- a/install.sh
+++ b/install.sh
@@ -14,15 +14,6 @@ cd ..
 cp AndroidSlidingUpPanel/library/build/outputs/aar/library-release.aar app/libs/library-release.aar
 rm AndroidSlidingUpPanel/local.properties
 
-# Build aspm
-echo sdk.dir=$ANDROID_HOME > aspm/local.properties
-cd aspm
-gradle clean build jar shadowJar
-cd ..
-cp aspm/annotations/build/libs/annotations.jar app/libs/annotations.jar
-cp aspm/compiler/build/libs/compiler-all.jar app/libs/compiler-all.jar
-rm aspm/local.properties
-
 # Build QuasselDroidNG
 echo sdk.dir=$ANDROID_HOME > local.properties
 gradle clean assembleRelease -x lintVitalRelease