diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 11dff78046526a3564ab59d66b6456baf7d1d02e..fa10b50859672779aaf7a82b165c24e6a7c2ba50 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -11,32 +11,28 @@
     android:icon="@mipmap/ic_launcher"
     android:label="@string/app_name"
     android:supportsRtl="true"
-    android:theme="@style/AppTheme">
+    android:theme="@style/Theme.SplashTheme">
     <activity
       android:name=".ui.ChatActivity"
       android:exported="false"
       android:label="@string/app_name"
-      android:theme="@style/SplashTheme"
       android:windowSoftInputMode="adjustResize" />
     <activity
       android:name=".ui.setup.accounts.AccountSetupActivity"
       android:exported="false"
       android:label="@string/app_name"
       android:parentActivityName=".ui.setup.accounts.AccountSelectionActivity"
-      android:theme="@style/SplashTheme"
       android:windowSoftInputMode="adjustResize" />
     <activity
       android:name=".ui.setup.accounts.AccountEditActivity"
       android:exported="false"
       android:label="@string/app_name"
       android:parentActivityName=".ui.setup.accounts.AccountSelectionActivity"
-      android:theme="@style/SplashTheme"
       android:windowSoftInputMode="adjustResize" />
     <activity
       android:name=".ui.setup.accounts.AccountSelectionActivity"
       android:exported="true"
       android:label="@string/app_name"
-      android:theme="@style/SplashTheme"
       android:windowSoftInputMode="adjustResize">
       <intent-filter>
         <action android:name="android.intent.action.MAIN" />
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/PersistentSession.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/PersistentSession.kt
new file mode 100644
index 0000000000000000000000000000000000000000..24b824652111f5ee489c2f96f144c8338902a209
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/PersistentSession.kt
@@ -0,0 +1,26 @@
+package de.kuschku.quasseldroid_ng.persistence
+
+import de.kuschku.libquassel.protocol.IdentityId
+import de.kuschku.libquassel.protocol.NetworkId
+import de.kuschku.libquassel.quassel.syncables.*
+import de.kuschku.libquassel.session.ConnectionState
+import de.kuschku.libquassel.session.ISession
+import io.reactivex.subjects.BehaviorSubject
+
+class PersistentSession : ISession {
+  override val aliasManager: AliasManager? = null
+  override val backlogManager: BacklogManager? = null
+  override val bufferSyncer: BufferSyncer? = null
+  override val bufferViewManager: BufferViewManager? = null
+  override val certManagers: Map<IdentityId, CertManager> = emptyMap()
+  override val coreInfo: CoreInfo? = null
+  override val dccConfig: DccConfig? = null
+  override val identities: Map<IdentityId, Identity> = emptyMap()
+  override val ignoreListManager: IgnoreListManager? = null
+  override val ircListHelper: IrcListHelper? = null
+  override val networks: Map<NetworkId, Network> = emptyMap()
+  override val networkConfig: NetworkConfig? = null
+
+  override fun close() = Unit
+  override val state = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED)
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselDatabase.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselDatabase.kt
index f4463a670556b4b9329208a60d31ee927daf4925..3b07cd915b0a97fdbfe75d2b862b79395c1f62ce 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselDatabase.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselDatabase.kt
@@ -57,6 +57,12 @@ abstract class QuasselDatabase : RoomDatabase() {
     var networkName: String
   )
 
+  @Entity
+  class BufferViewConfig(
+    @PrimaryKey var id: Int,
+    var name: String
+  )
+
   @Dao
   interface NetworkDao {
     @Insert(onConflict = OnConflictStrategy.REPLACE)
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
index ed212b2e0580fc1fa608954cdd0264e6b6619bad..a1b4123ec452ddb8e8e6c225071ecb60a5c8d54c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
@@ -7,11 +7,11 @@ import android.os.Handler
 import android.os.HandlerThread
 import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.session.Backend
-import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.session.SessionManager
 import de.kuschku.libquassel.session.SocketAddress
 import de.kuschku.quasseldroid_ng.BuildConfig
 import de.kuschku.quasseldroid_ng.R
+import de.kuschku.quasseldroid_ng.persistence.PersistentSession
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
 import de.kuschku.quasseldroid_ng.util.compatibility.AndroidHandlerService
 import org.threeten.bp.Instant
@@ -78,7 +78,7 @@ class QuasselService : LifecycleService() {
     handler = Handler(thread.looper)
     super.onCreate()
     database = QuasselDatabase.Creator.init(application)
-    sessionManager = SessionManager(ISession.NULL)
+    sessionManager = SessionManager(PersistentSession())
     clientData = ClientData(
       identifier = "${resources.getString(R.string.app_name)} ${BuildConfig.VERSION_NAME}",
       buildDate = Instant.ofEpochSecond(BuildConfig.GIT_COMMIT_DATE),
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/ChatActivity.kt
index 1bc376a8f4d7ff6a814740f48f0cc271a82b2dd3..e9bf43aaed72769a5f83cddfe2aab6dbdcd67975 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/ChatActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/ChatActivity.kt
@@ -1,14 +1,13 @@
 package de.kuschku.quasseldroid_ng.ui
 
 import android.app.Activity
-import android.arch.lifecycle.LiveDataReactiveStreams
 import android.arch.lifecycle.Observer
 import android.content.Context
-import android.content.Intent
 import android.os.Bundle
 import android.os.Handler
 import android.os.HandlerThread
 import android.support.design.widget.Snackbar
+import android.support.v7.widget.Toolbar
 import android.util.Log
 import android.view.Menu
 import android.view.MenuItem
@@ -16,17 +15,16 @@ import android.widget.Button
 import android.widget.TextView
 import butterknife.BindView
 import butterknife.ButterKnife
-import de.kuschku.libquassel.session.Backend
-import de.kuschku.libquassel.session.ConnectionState
-import de.kuschku.libquassel.session.SocketAddress
+import de.kuschku.libquassel.session.*
 import de.kuschku.libquassel.util.compatibility.LoggingHandler
+import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.ERROR
+import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO
+import de.kuschku.libquassel.util.compatibility.log
 import de.kuschku.quasseldroid_ng.Keys
 import de.kuschku.quasseldroid_ng.R
 import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
-import de.kuschku.quasseldroid_ng.service.QuasselService
-import de.kuschku.quasseldroid_ng.util.helper.editApply
-import de.kuschku.quasseldroid_ng.util.helper.stickyMapNotNull
-import de.kuschku.quasseldroid_ng.util.helper.stickySwitchMapNotNull
+import de.kuschku.quasseldroid_ng.util.helper.*
+import de.kuschku.quasseldroid_ng.util.service.ServiceBoundActivity
 import org.threeten.bp.ZoneOffset
 import org.threeten.bp.ZonedDateTime
 import org.threeten.bp.format.DateTimeFormatter
@@ -44,19 +42,35 @@ class ChatActivity : ServiceBoundActivity() {
   @BindView(R.id.errorList)
   lateinit var errorList: TextView
 
+  @BindView(R.id.toolbar)
+  lateinit var toolbar: Toolbar
+
   private val thread = HandlerThread("Chat")
   private lateinit var handler: Handler
 
-  private val state = backend.stickyMapNotNull(null, Backend::sessionManager)
-    .stickySwitchMapNotNull(ConnectionState.DISCONNECTED) { session ->
-      LiveDataReactiveStreams.fromPublisher(session.state)
+  private val sessionManager = backend.map(Backend::sessionManager)
+  private val state
+    = sessionManager.switchMapRx(SessionManager::state)
+
+  private val bufferViewManager
+    = sessionManager.switchMapRx(SessionManager::session).map(ISession::bufferViewManager)
+  private val bufferViewConfigs = bufferViewManager.switchMapRx { manager ->
+    manager.bufferViewConfigIds.map { ids ->
+      ids.map { id ->
+        manager.bufferViewConfig(id)
+      }.sortedBy { it?.bufferViewName() }
     }
+  }
 
-  private var snackbar: Snackbar? = null
+  private
+  var snackbar: Snackbar? = null
 
-  private val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ISO_TIME
-  private val logHandler = object : LoggingHandler() {
-    override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
+  private
+  val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ISO_TIME
+  private
+  val logHandler = object : LoggingHandler() {
+    override fun log(logLevel: LogLevel, tag: String, message: String?,
+                     throwable: Throwable?) {
       val time = dateTimeFormatter.format(ZonedDateTime.now(ZoneOffset.UTC))
       runOnUiThread {
         errorList.append("$time $tag: ")
@@ -72,7 +86,7 @@ class ChatActivity : ServiceBoundActivity() {
     }
 
     override fun isLoggable(logLevel: LogLevel, tag: String)
-      = (logLevel.ordinal >= LogLevel.INFO.ordinal)
+      = (logLevel.ordinal >= INFO.ordinal)
   }
 
   override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
@@ -86,15 +100,15 @@ class ChatActivity : ServiceBoundActivity() {
   }
 
   var account: AccountDatabase.Account? = null
+
   override fun onCreate(savedInstanceState: Bundle?) {
     thread.start()
     handler = Handler(thread.looper)
 
-    startService(Intent(this, QuasselService::class.java))
-    setTheme(R.style.AppTheme)
     super.onCreate(savedInstanceState)
     setContentView(R.layout.activity_main)
     ButterKnife.bind(this)
+    setSupportActionBar(toolbar)
 
     val database = AccountDatabase.Creator.init(this)
     handler.post {
@@ -130,7 +144,7 @@ class ChatActivity : ServiceBoundActivity() {
       errorList.text = ""
     }
 
-    state.observe(this, Observer {
+    state.observeSticky(this, Observer {
       val status = it ?: ConnectionState.DISCONNECTED
       val disconnected = status == ConnectionState.DISCONNECTED
 
@@ -141,6 +155,13 @@ class ChatActivity : ServiceBoundActivity() {
       snackbar = Snackbar.make(errorList, status.name, Snackbar.LENGTH_SHORT)
       snackbar?.show()
     })
+
+    bufferViewManager.observeSticky(this, Observer {
+      log(ERROR, "bufferViewManager", it.toString())
+    })
+    bufferViewConfigs.or(emptyList()).observeSticky(this, Observer {
+      log(ERROR, "bufferViewConfigs", it.toString())
+    })
   }
 
   override fun onCreateOptionsMenu(menu: Menu?): Boolean {
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/SetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/SetupActivity.kt
index 8991a7e38d2e94b792077b2437482dadc1367b3e..0493f46823c5f41b046b18c12ed26bfe833c7ce0 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/SetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/SetupActivity.kt
@@ -14,7 +14,9 @@ import android.view.ViewGroup
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.quasseldroid_ng.R
-import de.kuschku.quasseldroid_ng.util.helper.stickySwitchMapNotNull
+import de.kuschku.quasseldroid_ng.util.helper.observeSticky
+import de.kuschku.quasseldroid_ng.util.helper.or
+import de.kuschku.quasseldroid_ng.util.helper.switchMap
 
 abstract class SetupActivity : AppCompatActivity() {
   @BindView(R.id.view_pager)
@@ -28,7 +30,7 @@ abstract class SetupActivity : AppCompatActivity() {
   protected abstract val fragments: List<SlideFragment>
 
   private val currentPage = MutableLiveData<SlideFragment?>()
-  private val isValid = currentPage.stickySwitchMapNotNull(false, SlideFragment::valid)
+  private val isValid = currentPage.switchMap(SlideFragment::valid).or(false)
 
   private val pageChangeListener = object : ViewPager.OnPageChangeListener {
     override fun onPageScrollStateChanged(state: Int) {
@@ -53,7 +55,7 @@ abstract class SetupActivity : AppCompatActivity() {
   }
 
   override fun onCreate(savedInstanceState: Bundle?) {
-    setTheme(R.style.SetupTheme)
+    setTheme(R.style.Theme_SetupTheme)
     super.onCreate(savedInstanceState)
     setContentView(R.layout.activity_setup)
     ButterKnife.bind(this)
@@ -68,7 +70,7 @@ abstract class SetupActivity : AppCompatActivity() {
       else
         viewPager.setCurrentItem(viewPager.currentItem + 1, true)
     }
-    isValid.observe(this, Observer {
+    isValid.observeSticky(this, Observer {
       if (it == true) {
         button.show()
         adapter.lastValidItem = viewPager.currentItem
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountEditActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountEditActivity.kt
index d6500de7580ee08c7e76fa3cf98e01c018bcf756..ba542dabb28e7fb112e95459a0ba371aef5e8cc0 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountEditActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountEditActivity.kt
@@ -58,7 +58,7 @@ class AccountEditActivity : AppCompatActivity() {
     thread.start()
     handler = Handler(thread.looper)
 
-    setTheme(R.style.AppTheme)
+    setTheme(R.style.Theme_AppTheme_Light)
     super.onCreate(savedInstanceState)
     setContentView(R.layout.setup_account_edit)
     ButterKnife.bind(this)
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..aa95e41c5574f92ecadbbc85957ac5600a1b66da
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt
@@ -0,0 +1,117 @@
+package de.kuschku.quasseldroid_ng.util.helper
+
+import android.arch.lifecycle.*
+import android.support.annotation.MainThread
+import de.kuschku.libquassel.util.helpers.toLiveData
+import io.reactivex.BackpressureStrategy
+import io.reactivex.Observable
+
+@MainThread
+inline fun <X, Y> LiveData<X?>.switchMap(
+  noinline func: (X) -> LiveData<Y>?
+): LiveData<Y> {
+  val result = MediatorLiveData<Y>()
+  result.addSource(this, object : Observer<X?> {
+    internal var mSource: LiveData<Y>? = null
+
+    override fun onChanged(x: X?) {
+      val newLiveData = if (x == null) null else func(x)
+      if (mSource === newLiveData) {
+        return
+      }
+      if (mSource != null) {
+        result.removeSource(mSource)
+      }
+      mSource = newLiveData
+      if (mSource != null) {
+        result.addSource(mSource) { y -> result.value = y }
+      } else {
+        result.value = null
+      }
+    }
+  })
+  return result
+}
+
+@MainThread
+inline fun <X, Y> LiveData<X?>.switchMapRx(
+  strategy: BackpressureStrategy,
+  noinline func: (X) -> Observable<Y>?
+): LiveData<Y> {
+  val result = MediatorLiveData<Y>()
+  result.addSource(this, object : Observer<X?> {
+    internal var mSource: LiveData<Y>? = null
+
+    override fun onChanged(x: X?) {
+      val newLiveData = if (x == null) null else func(x)?.toLiveData(strategy)
+      if (mSource === newLiveData) {
+        return
+      }
+      if (mSource != null) {
+        result.removeSource(mSource)
+      }
+      mSource = newLiveData
+      if (mSource != null) {
+        result.addSource(mSource) { y -> result.value = y }
+      } else {
+        result.value = null
+      }
+    }
+  })
+  return result
+}
+
+@MainThread
+inline fun <X, Y> LiveData<X?>.switchMapRx(
+  noinline func: (X) -> Observable<Y>?
+): LiveData<Y> = switchMapRx(BackpressureStrategy.LATEST, func)
+
+@MainThread
+inline fun <X, Y> LiveData<X?>.map(
+  noinline func: (X) -> Y?
+): LiveData<Y?> {
+  val result = MediatorLiveData<Y?>()
+  result.addSource(this) { x ->
+    result.value = if (x == null) null else func.invoke(x)
+  }
+  return result
+}
+
+@MainThread
+inline fun <X> LiveData<X>.orElse(
+  noinline func: () -> X
+): LiveData<X> {
+  val result = object : MediatorLiveData<X>() {
+    override fun getValue() = super.getValue() ?: func()
+  }
+  result.addSource(this) { x ->
+    result.value = x ?: func()
+  }
+  return result
+}
+
+@MainThread
+inline fun <X> LiveData<X>.or(
+  default: X
+): LiveData<X> {
+  val result = object : MediatorLiveData<X>() {
+    override fun getValue() = super.getValue() ?: default
+  }
+  result.addSource(this) { x ->
+    result.value = x ?: default
+  }
+  return result
+}
+
+inline fun <T> LiveData<T>.observeSticky(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
+  observe(lifecycleOwner, observer)
+  observer.onChanged(value)
+}
+
+inline fun <T> LiveData<T>.observeForeverSticky(observer: Observer<T>) {
+  observeForever(observer)
+  observer.onChanged(value)
+}
+
+inline fun <T> LiveData<T>.toObservable(lifecycleOwner: LifecycleOwner)
+  = Observable.fromPublisher(LiveDataReactiveStreams.toPublisher(lifecycleOwner, this))
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ObservableHelper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ObservableHelper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3bb0e08be8350411c415cd24981f8b4919156e84
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ObservableHelper.kt
@@ -0,0 +1,9 @@
+package de.kuschku.libquassel.util.helpers
+
+import android.arch.lifecycle.LiveDataReactiveStreams
+import io.reactivex.BackpressureStrategy
+import io.reactivex.Observable
+
+inline fun <T> Observable<T>.toLiveData(
+  strategy: BackpressureStrategy = BackpressureStrategy.LATEST)
+  = LiveDataReactiveStreams.fromPublisher(toFlowable(strategy))
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/TransformationsHelper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/TransformationsHelper.kt
deleted file mode 100644
index ad934b62b48aba3ff1f55b02317fa5b1ade9161f..0000000000000000000000000000000000000000
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/TransformationsHelper.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-package de.kuschku.quasseldroid_ng.util.helper
-
-import android.arch.lifecycle.LifecycleOwner
-import android.arch.lifecycle.LiveData
-import android.arch.lifecycle.MediatorLiveData
-import android.arch.lifecycle.Observer
-import android.support.annotation.MainThread
-
-@MainThread
-fun <X, Y> LiveData<X?>.stickySwitchMapNotNull(
-  defaultValue: Y,
-  func: (X) -> LiveData<Y>?
-): LiveData<Y> {
-  val result = object : MediatorLiveData<Y>() {
-    override fun observe(owner: LifecycleOwner?, observer: Observer<Y>?) {
-      super.observe(owner, observer)
-      observer?.onChanged(value ?: defaultValue)
-    }
-
-    override fun observeForever(observer: Observer<Y>?) {
-      super.observeForever(observer)
-      observer?.onChanged(value ?: defaultValue)
-    }
-  }
-  result.addSource(this, object : Observer<X?> {
-    internal var mSource: LiveData<Y>? = null
-
-    override fun onChanged(x: X?) {
-      val newLiveData = if (x != null) func(x) else null
-      if (mSource === newLiveData) {
-        return
-      }
-      if (mSource != null) {
-        result.removeSource(mSource)
-      }
-      mSource = newLiveData
-      if (mSource != null) {
-        result.addSource(mSource) { y -> result.value = y ?: defaultValue }
-      } else {
-        result.value = defaultValue
-      }
-    }
-  })
-  return result
-}
-
-@MainThread
-fun <X, Y> LiveData<X?>.switchMapNullable(
-  defaultValue: Y,
-  func: (X) -> LiveData<Y>?
-): LiveData<Y> {
-  val result = MediatorLiveData<Y>()
-  result.addSource(this, object : Observer<X?> {
-    internal var mSource: LiveData<Y>? = null
-
-    override fun onChanged(x: X?) {
-      val newLiveData = if (x != null) func(x) else null
-      if (mSource === newLiveData) {
-        return
-      }
-      if (mSource != null) {
-        result.removeSource(mSource)
-      }
-      mSource = newLiveData
-      if (mSource != null) {
-        result.addSource(mSource) { y -> result.value = y ?: defaultValue }
-      } else {
-        result.value = defaultValue
-      }
-    }
-  })
-  return result
-}
-
-@MainThread
-fun <X, Y> LiveData<X?>.stickyMapNotNull(
-  defaultValue: Y,
-  func: (X) -> Y?
-): LiveData<Y> {
-  val result = object : MediatorLiveData<Y>() {
-    override fun observe(owner: LifecycleOwner?, observer: Observer<Y>?) {
-      super.observe(owner, observer)
-      observer?.onChanged(value ?: defaultValue)
-    }
-
-    override fun observeForever(observer: Observer<Y>?) {
-      super.observeForever(observer)
-      observer?.onChanged(value ?: defaultValue)
-    }
-  }
-  result.addSource(this) { x ->
-    result.setValue(if (x == null) defaultValue else func(x) ?: defaultValue)
-  }
-  return result
-}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/ServiceBoundActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt
similarity index 79%
rename from app/src/main/java/de/kuschku/quasseldroid_ng/ui/ServiceBoundActivity.kt
rename to app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt
index e46c5ad4998e35d6f818b25e935335516de908ad..b7a6d0b4ef9148ed7883dd6bc7c507accde99916 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/ServiceBoundActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt
@@ -1,12 +1,14 @@
-package de.kuschku.quasseldroid_ng.ui
+package de.kuschku.quasseldroid_ng.util.service
 
 import android.arch.lifecycle.MutableLiveData
 import android.content.ComponentName
 import android.content.Intent
 import android.content.ServiceConnection
+import android.os.Bundle
 import android.os.IBinder
 import android.support.v7.app.AppCompatActivity
 import de.kuschku.libquassel.session.Backend
+import de.kuschku.quasseldroid_ng.R
 import de.kuschku.quasseldroid_ng.service.QuasselService
 
 abstract class ServiceBoundActivity : AppCompatActivity() {
@@ -31,6 +33,12 @@ abstract class ServiceBoundActivity : AppCompatActivity() {
     }
   }
 
+  override fun onCreate(savedInstanceState: Bundle?) {
+    setTheme(R.style.Theme_ChatTheme_Quassel_Light)
+    super.onCreate(savedInstanceState)
+    startService(Intent(this, QuasselService::class.java))
+  }
+
   override fun onStart() {
     bindService(Intent(this, QuasselService::class.java), connection, 0)
     super.onStart()
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/DrawerRecyclerView.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/DrawerRecyclerView.kt
new file mode 100644
index 0000000000000000000000000000000000000000..105cbb0e5c83eb842b264c4700556bb527d04e05
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/DrawerRecyclerView.kt
@@ -0,0 +1,104 @@
+package de.kuschku.quasseldroid_ng.util.ui
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.support.v4.view.ViewCompat
+import android.support.v4.view.WindowInsetsCompat
+import android.support.v7.widget.RecyclerView
+import android.util.AttributeSet
+import de.kuschku.quasseldroid_ng.R
+
+class DrawerRecyclerView @JvmOverloads constructor(
+  context: Context,
+  attrs: AttributeSet? = null,
+  defStyleAttr: Int = 0
+) : RecyclerView(context, attrs, defStyleAttr) {
+  private var mInsetForeground: Drawable? = null
+  private var mInsets: Rect? = null
+  private val mTempRect = Rect()
+  private val maxWidth: Int
+
+  init {
+    val a = context.obtainStyledAttributes(attrs,
+                                           R.styleable.ScrimInsetsFrameLayout, defStyleAttr,
+                                           R.style.Widget_Design_ScrimInsetsFrameLayout)
+    mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsFrameLayout_insetForeground)
+    a.recycle()
+    setWillNotDraw(true) // No need to draw until the insets are adjusted
+    ViewCompat.setOnApplyWindowInsetsListener(this
+    ) { v, insets ->
+      if (null == mInsets) {
+        mInsets = Rect()
+      }
+      mInsets!!.set(insets.systemWindowInsetLeft,
+                    insets.systemWindowInsetTop,
+                    insets.systemWindowInsetRight,
+                    insets.systemWindowInsetBottom)
+      setPadding(insets.systemWindowInsetLeft,
+                 insets.systemWindowInsetTop,
+                 insets.systemWindowInsetRight,
+                 insets.systemWindowInsetBottom)
+      onInsetsChanged(insets)
+      setWillNotDraw(!insets.hasSystemWindowInsets() || mInsetForeground == null)
+      ViewCompat.postInvalidateOnAnimation(this@DrawerRecyclerView)
+      insets.consumeSystemWindowInsets()
+    }
+
+    maxWidth = context.resources.getDimensionPixelSize(R.dimen.navigation_drawer_max_width)
+  }
+
+  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+    super.onMeasure(
+      MeasureSpec.makeMeasureSpec(
+        Math.min(MeasureSpec.getSize(widthMeasureSpec), maxWidth),
+        MeasureSpec.getMode(widthMeasureSpec)
+      ),
+      heightMeasureSpec
+    )
+  }
+
+  override fun draw(canvas: Canvas) {
+    super.draw(canvas)
+    val width = width
+    val height = height
+    if (mInsets != null && mInsetForeground != null) {
+      val sc = canvas.save()
+      canvas.translate(scrollX.toFloat(), scrollY.toFloat())
+      // Top
+      mTempRect.set(0, 0, width, mInsets!!.top)
+      mInsetForeground!!.bounds = mTempRect
+      mInsetForeground!!.draw(canvas)
+      // Bottom
+      mTempRect.set(0, height - mInsets!!.bottom, width, height)
+      mInsetForeground!!.bounds = mTempRect
+      mInsetForeground!!.draw(canvas)
+      // Left
+      mTempRect.set(0, mInsets!!.top, mInsets!!.left, height - mInsets!!.bottom)
+      mInsetForeground!!.bounds = mTempRect
+      mInsetForeground!!.draw(canvas)
+      // Right
+      mTempRect.set(width - mInsets!!.right, mInsets!!.top, width, height - mInsets!!.bottom)
+      mInsetForeground!!.bounds = mTempRect
+      mInsetForeground!!.draw(canvas)
+      canvas.restoreToCount(sc)
+    }
+  }
+
+  override fun onAttachedToWindow() {
+    super.onAttachedToWindow()
+    if (mInsetForeground != null) {
+      mInsetForeground!!.callback = this
+    }
+  }
+
+  override fun onDetachedFromWindow() {
+    super.onDetachedFromWindow()
+    if (mInsetForeground != null) {
+      mInsetForeground!!.callback = null
+    }
+  }
+
+  protected open fun onInsetsChanged(insets: WindowInsetsCompat) {}
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/NavigationDrawerLayout.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/NavigationDrawerLayout.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2371bc628527f494a9543562d770891b25a67844
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/NavigationDrawerLayout.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package de.kuschku.quasseldroid_ng.util.ui
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.support.v4.view.ViewCompat
+import android.support.v4.view.WindowInsetsCompat
+import android.util.AttributeSet
+import android.widget.FrameLayout
+import de.kuschku.quasseldroid_ng.R
+
+class NavigationDrawerLayout @JvmOverloads constructor(
+  context: Context,
+  attrs: AttributeSet? = null,
+  defStyleAttr: Int = 0
+) : FrameLayout(context, attrs, defStyleAttr) {
+  private var mInsetForeground: Drawable? = null
+  private var mInsets: Rect? = null
+  private val mTempRect = Rect()
+  private val maxWidth: Int
+
+  init {
+    val a = context.obtainStyledAttributes(attrs,
+                                           R.styleable.ScrimInsetsFrameLayout, defStyleAttr,
+                                           R.style.Widget_Design_ScrimInsetsFrameLayout)
+    mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsFrameLayout_insetForeground)
+    a.recycle()
+    setWillNotDraw(true) // No need to draw until the insets are adjusted
+    ViewCompat.setOnApplyWindowInsetsListener(this
+    ) { v, insets ->
+      if (null == mInsets) {
+        mInsets = Rect()
+      }
+      mInsets!!.set(insets.systemWindowInsetLeft,
+                    insets.systemWindowInsetTop,
+                    insets.systemWindowInsetRight,
+                    insets.systemWindowInsetBottom)
+      setPadding(insets.systemWindowInsetLeft,
+                 insets.systemWindowInsetTop,
+                 insets.systemWindowInsetRight,
+                 insets.systemWindowInsetBottom)
+      onInsetsChanged(insets)
+      setWillNotDraw(!insets.hasSystemWindowInsets() || mInsetForeground == null)
+      ViewCompat.postInvalidateOnAnimation(this@NavigationDrawerLayout)
+      insets.consumeSystemWindowInsets()
+    }
+
+    maxWidth = context.resources.getDimensionPixelSize(R.dimen.navigation_drawer_max_width)
+  }
+
+  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+    super.onMeasure(
+      MeasureSpec.makeMeasureSpec(
+        Math.min(MeasureSpec.getSize(widthMeasureSpec), maxWidth),
+        MeasureSpec.getMode(widthMeasureSpec)
+      ),
+      heightMeasureSpec
+    )
+  }
+
+  override fun draw(canvas: Canvas) {
+    super.draw(canvas)
+    val width = width
+    val height = height
+    if (mInsets != null && mInsetForeground != null) {
+      val sc = canvas.save()
+      canvas.translate(scrollX.toFloat(), scrollY.toFloat())
+      // Top
+      mTempRect.set(0, 0, width, mInsets!!.top)
+      mInsetForeground!!.bounds = mTempRect
+      mInsetForeground!!.draw(canvas)
+      // Bottom
+      mTempRect.set(0, height - mInsets!!.bottom, width, height)
+      mInsetForeground!!.bounds = mTempRect
+      mInsetForeground!!.draw(canvas)
+      // Left
+      mTempRect.set(0, mInsets!!.top, mInsets!!.left, height - mInsets!!.bottom)
+      mInsetForeground!!.bounds = mTempRect
+      mInsetForeground!!.draw(canvas)
+      // Right
+      mTempRect.set(width - mInsets!!.right, mInsets!!.top, width, height - mInsets!!.bottom)
+      mInsetForeground!!.bounds = mTempRect
+      mInsetForeground!!.draw(canvas)
+      canvas.restoreToCount(sc)
+    }
+  }
+
+  override fun onAttachedToWindow() {
+    super.onAttachedToWindow()
+    if (mInsetForeground != null) {
+      mInsetForeground!!.callback = this
+    }
+  }
+
+  override fun onDetachedFromWindow() {
+    super.onDetachedFromWindow()
+    if (mInsetForeground != null) {
+      mInsetForeground!!.callback = null
+    }
+  }
+
+  protected open fun onInsetsChanged(insets: WindowInsetsCompat) {}
+}
diff --git a/app/src/main/res/drawable/bg_intro.xml b/app/src/main/res/drawable/bg_intro.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1ade9669ad68db6d4c9b6aace31bded678ce60e5
--- /dev/null
+++ b/app/src/main/res/drawable/bg_intro.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+  android:width="1440dp"
+  android:height="810dp"
+  android:viewportHeight="810"
+  android:viewportWidth="1440">
+
+  <path
+    android:fillColor="#d7d7d7"
+    android:pathData="M 0 0 L 0 810 L 1440 810 L 1440 0 L 0 0 z" />
+  <path
+    android:fillColor="#dcdcdc"
+    android:pathData="M 259.01562 810 L 1440 810 L 1440 0 L 745.32812 0 L 97.171875 648.15625 L 259.01562 810 z" />
+  <path
+    android:fillColor="#e1e1e1"
+    android:pathData="M 556.24609 810 L 1440 810 L 1440 0 L 1366.2441 0 L 556.24609 810 z" />
+  <path
+    android:fillColor="#e6e6e6"
+    android:pathData="M 644.31836 810 L 1440 810 L 1440 14.318359 L 644.31836 810 z" />
+  <path
+    android:fillColor="#ebebeb"
+    android:pathData="M 1439.0195 810 L 1440 810 L 1440 270.47656 L 1169.748 540.72852 L 1439.0195 810z" />
+  <path
+    android:fillColor="#f0f0f0"
+    android:pathData="M 900.47656 810 L 1440 810 L 1440 805.58203 L 1172.4473 538.0293 L 900.47656 810z" />
+  <path
+    android:fillColor="#f5f5f5"
+    android:pathData="M 334.24023 0 L 0 0 L 0 810 L 1144.2402 810 L 334.24023 0 z" />
+  <path
+    android:fillColor="#fafafa"
+    android:pathData="M 0 455.43359 L 0 810 L 354.56836 810 L 0 455.43359 z" />
+  <path
+    android:fillColor="#ffffff"
+    android:pathData="M 0 536.39453 L 0 810 L 273.60547 810 L 0 536.39453 z" />
+</vector>
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 2f767fd2961521820dace4d4923f0e5cb659a46a..ebbea8d560a06dab78280fd5c9a774237fbfbc85 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,50 +1,63 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.v4.widget.DrawerLayout 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/drawer_layout"
   android:layout_width="match_parent"
-  android:layout_height="match_parent">
+  android:layout_height="match_parent"
+  android:fitsSystemWindows="true"
+  tools:openDrawer="start">
 
-  <LinearLayout
+  <include layout="@layout/content_main" />
+
+  <de.kuschku.quasseldroid_ng.util.ui.DrawerRecyclerView
+    android:id="@+id/nickList"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="end"
+    android:background="?android:attr/windowBackground"
+    android:clipToPadding="false"
+    android:fitsSystemWindows="true" />
+
+  <de.kuschku.quasseldroid_ng.util.ui.NavigationDrawerLayout
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_marginBottom="8dp"
-    android:layout_marginTop="8dp"
-    android:orientation="vertical"
-    android:paddingLeft="24dp"
-    android:paddingRight="24dp">
+    android:layout_height="match_parent"
+    android:layout_gravity="start"
+    android:background="?android:attr/windowBackground"
+    android:fitsSystemWindows="true"
+    app:insetForeground="?attr/colorPrimaryDark">
 
     <LinearLayout
       android:layout_width="match_parent"
-      android:layout_height="wrap_content">
+      android:layout_height="match_parent"
+      android:orientation="vertical">
 
-      <Button
-        android:id="@+id/connect"
-        android:layout_width="wrap_content"
+      <android.support.design.widget.AppBarLayout
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:minWidth="88dp"
-        android:text="Connect"
-        android:theme="@style/AppTheme.Button.Colored" />
+        android:theme="?attr/actionBarTheme">
 
-      <Button
-        android:id="@+id/disconnect"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minWidth="88dp"
-        android:text="Disconnect"
-        android:theme="@style/AppTheme.Button" />
+        <android.support.v7.widget.Toolbar
+          android:id="@+id/toolbar"
+          android:layout_width="match_parent"
+          android:layout_height="?attr/actionBarSize"
+          android:background="?attr/colorPrimary"
+          app:contentInsetStartWithNavigation="0dp">
 
-      <Button
-        android:id="@+id/clear"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minWidth="88dp"
-        android:text="Clear"
-        android:theme="@style/AppTheme.Button" />
-    </LinearLayout>
+          <android.support.v7.widget.AppCompatSpinner
+            android:id="@+id/chatListSpinner"
+            android:layout_width="fill_parent"
+            android:layout_height="match_parent"
+            android:theme="?attr/actionBarTheme" />
 
-    <TextView
-      android:id="@+id/errorList"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:textIsSelectable="true" />
-  </LinearLayout>
-</ScrollView>
+        </android.support.v7.widget.Toolbar>
+
+      </android.support.design.widget.AppBarLayout>
+
+
+      <android.support.v7.widget.RecyclerView
+        android:id="@+id/chatList"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+    </LinearLayout>
+  </de.kuschku.quasseldroid_ng.util.ui.NavigationDrawerLayout>
+</android.support.v4.widget.DrawerLayout>
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4984d3789756b6101de591c7cd1159a7ddf92b1
--- /dev/null
+++ b/app/src/main/res/layout/content_main.xml
@@ -0,0 +1,128 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  xmlns:app="http://schemas.android.com/apk/res-auto"
+  android:layout_width="match_parent"
+  android:layout_height="match_parent"
+  android:fitsSystemWindows="true"
+  android:orientation="vertical">
+
+  <android.support.design.widget.AppBarLayout
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:theme="?attr/actionBarTheme">
+
+    <android.support.v7.widget.Toolbar
+      android:id="@+id/toolbar"
+      android:layout_width="match_parent"
+      android:layout_height="?attr/actionBarSize"
+      android:background="?attr/colorPrimary"
+      app:contentInsetStartWithNavigation="0dp">
+
+      <LinearLayout
+        android:id="@+id/toolbar_action_area"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:background="?attr/selectableItemBackgroundBorderless"
+        android:clickable="true"
+        android:focusable="true"
+        android:focusableInTouchMode="false"
+        android:gravity="center_vertical|start"
+        android:minHeight="?attr/actionBarSize"
+        android:orientation="vertical">
+
+        <LinearLayout
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_gravity="center_vertical"
+          android:layout_marginTop="-2dp"
+          android:baselineAligned="false"
+          android:gravity="center_vertical">
+
+          <TextView
+            android:id="@+id/key"
+            style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
+            android:layout_marginEnd="2dp"
+            android:layout_marginRight="2dp"
+            android:layout_marginTop="2dp"
+            android:gravity="center"
+            android:textSize="16sp"
+            android:visibility="gone" />
+
+          <TextView
+            android:id="@+id/toolbar_title"
+            style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ellipsize="end"
+            android:gravity="center_vertical"
+            android:singleLine="true"
+            android:text="@string/app_name" />
+
+        </LinearLayout>
+
+        <TextView
+          android:id="@+id/toolbar_subtitle"
+          style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_marginTop="-3dp"
+          android:ellipsize="end"
+          android:singleLine="true"
+          android:visibility="gone" />
+      </LinearLayout>
+
+    </android.support.v7.widget.Toolbar>
+
+  </android.support.design.widget.AppBarLayout>
+
+  <ScrollView
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:layout_marginBottom="8dp"
+      android:layout_marginTop="8dp"
+      android:orientation="vertical"
+      android:paddingLeft="24dp"
+      android:paddingRight="24dp">
+
+      <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <Button
+          android:id="@+id/connect"
+          style="@style/Widget.Button.Colored"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:minWidth="88dp"
+          android:text="Connect" />
+
+        <Button
+          android:id="@+id/disconnect"
+          style="@style/Widget.Button"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:minWidth="88dp"
+          android:text="Disconnect" />
+
+        <Button
+          android:id="@+id/clear"
+          style="@style/Widget.Button"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:minWidth="88dp"
+          android:text="Clear" />
+      </LinearLayout>
+
+      <TextView
+        android:id="@+id/errorList"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textIsSelectable="true" />
+    </LinearLayout>
+  </ScrollView>
+</LinearLayout>
diff --git a/app/src/main/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d5591b01943f2b7105b52250a6640ad0eb936c13
--- /dev/null
+++ b/app/src/main/res/values-sw600dp/dimens.xml
@@ -0,0 +1,3 @@
+<resources>
+  <dimen name="navigation_drawer_max_width">400dp</dimen>
+</resources>
diff --git a/app/src/main/res/values-sw600dp/styles.xml b/app/src/main/res/values-sw600dp/themes_base.xml
similarity index 58%
rename from app/src/main/res/values-sw600dp/styles.xml
rename to app/src/main/res/values-sw600dp/themes_base.xml
index 62a61762872f1553b16bad8ec6de6ac687cb3cce..424f44028f5b4059997759fd204cb07383d91db0 100644
--- a/app/src/main/res/values-sw600dp/styles.xml
+++ b/app/src/main/res/values-sw600dp/themes_base.xml
@@ -1,6 +1,6 @@
 <resources>
 
-  <style name="SetupTheme" parent="AppTheme.NoActionBar">
+  <style name="Theme.SetupTheme" parent="Theme.AppTheme.Light.NoActionBar">
     <item name="android:windowBackground">?attr/colorPrimary</item>
   </style>
 </resources>
diff --git a/app/src/main/res/values-v21/themes_base.xml b/app/src/main/res/values-v21/themes_base.xml
new file mode 100644
index 0000000000000000000000000000000000000000..128214dfe23956b650f7350f91062a11c9966e86
--- /dev/null
+++ b/app/src/main/res/values-v21/themes_base.xml
@@ -0,0 +1,26 @@
+<resources>
+
+  <style name="Theme.AppTheme.NoActionBar" parent="Theme.AppCompat.NoActionBar">
+    <item name="colorPrimary">@color/colorPrimary</item>
+    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+    <item name="colorAccent">@color/colorAccent</item>
+    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+    <item name="android:statusBarColor">?attr/colorPrimaryDark</item>
+  </style>
+
+  <style name="Theme.AppTheme.Light.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
+    <item name="colorPrimary">@color/colorPrimary</item>
+    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+    <item name="colorAccent">@color/colorAccent</item>
+    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+    <item name="android:statusBarColor">?attr/colorPrimaryDark</item>
+  </style>
+
+  <style name="Base.ChatTheme" parent="Theme.AppTheme.NoActionBar">
+    <item name="android:statusBarColor">#0000</item>
+  </style>
+
+  <style name="Base.ChatTheme.Light" parent="Theme.AppTheme.Light.NoActionBar">
+    <item name="android:statusBarColor">#0000</item>
+  </style>
+</resources>
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..46a053646ce0fed01fb5e8b8740b82110e0b67e2
--- /dev/null
+++ b/app/src/main/res/values/attrs.xml
@@ -0,0 +1,70 @@
+<resources>
+  <!-- sender colors -->
+  <attr name="senderColor0" format="color" />
+  <attr name="senderColor1" format="color" />
+  <attr name="senderColor2" format="color" />
+  <attr name="senderColor3" format="color" />
+  <attr name="senderColor4" format="color" />
+  <attr name="senderColor5" format="color" />
+  <attr name="senderColor6" format="color" />
+  <attr name="senderColor7" format="color" />
+  <attr name="senderColor8" format="color" />
+  <attr name="senderColor9" format="color" />
+  <attr name="senderColorA" format="color" />
+  <attr name="senderColorB" format="color" />
+  <attr name="senderColorC" format="color" />
+  <attr name="senderColorD" format="color" />
+  <attr name="senderColorE" format="color" />
+  <attr name="senderColorF" format="color" />
+
+  <!-- mirc colors -->
+  <attr name="mircColor0" format="color" />
+  <attr name="mircColor1" format="color" />
+  <attr name="mircColor2" format="color" />
+  <attr name="mircColor3" format="color" />
+  <attr name="mircColor4" format="color" />
+  <attr name="mircColor5" format="color" />
+  <attr name="mircColor6" format="color" />
+  <attr name="mircColor7" format="color" />
+  <attr name="mircColor8" format="color" />
+  <attr name="mircColor9" format="color" />
+  <attr name="mircColorA" format="color" />
+  <attr name="mircColorB" format="color" />
+  <attr name="mircColorC" format="color" />
+  <attr name="mircColorD" format="color" />
+  <attr name="mircColorE" format="color" />
+  <attr name="mircColorF" format="color" />
+
+  <!-- Background and foreground colors for UI -->
+  <attr name="colorForeground" format="color" />
+  <attr name="colorForegroundHighlight" format="color" />
+  <attr name="colorForegroundSecondary" format="color" />
+  <attr name="colorForegroundAction" format="color" />
+  <attr name="colorForegroundError" format="color" />
+
+  <attr name="colorForegroundMirc" format="integer" />
+
+  <attr name="colorDivider" format="color" />
+
+  <attr name="colorBackground" format="color" />
+  <attr name="colorBackgroundHighlight" format="color" />
+  <attr name="colorBackgroundSecondary" format="color" />
+  <attr name="colorBackgroundCard" format="color" />
+  <attr name="colorBackgroundDialog" format="color" />
+
+  <!-- Tint colors for drawer -->
+  <attr name="colorTintActivity" format="color" />
+  <attr name="colorTintMessage" format="color" />
+  <attr name="colorTintHighlight" format="color" />
+  <attr name="chatlineExpandedSize" />
+
+  <!-- Icons -->
+  <attr name="colorOffline" format="color" />
+  <attr name="colorAway" format="color" />
+  <attr name="colorFill" format="color" />
+
+  <attr name="formatBarTheme" format="reference" />
+  <attr name="buttonTheme" format="reference" />
+  <attr name="buttonThemeColored" format="reference" />
+  <attr name="cardStyle" format="reference" />
+</resources>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 3d2127148d95fdc23b4f6ec04c65d08f79df69ea..1b74be2c0c09054ae5886367863895f9eff7c065 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -3,4 +3,13 @@
   <color name="colorPrimary">#0a70c0</color>
   <color name="colorPrimaryDark">#105a94</color>
   <color name="colorAccent">#ffaf3b</color>
+
+  <color name="colorFillLight">#757575</color>
+  <color name="colorFillDark">#ffffff</color>
+
+  <color name="colorOfflineLight">#757575</color>
+  <color name="colorOfflineDark">#B3B3B3</color>
+
+  <color name="colorAwayLight">#959595</color>
+  <color name="colorAwayDark">#939393</color>
 </resources>
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4b085309263b5803199bd1e9b8e414b5185a313c
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,3 @@
+<resources>
+  <dimen name="navigation_drawer_max_width">320dp</dimen>
+</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
deleted file mode 100644
index 97b0c5a58e61c285190fc0c545f0661127837ce3..0000000000000000000000000000000000000000
--- a/app/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<resources>
-
-  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
-    <item name="colorPrimary">@color/colorPrimary</item>
-    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
-    <item name="colorAccent">@color/colorAccent</item>
-  </style>
-
-  <style name="AppTheme.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
-    <item name="colorPrimary">@color/colorPrimary</item>
-    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
-    <item name="colorAccent">@color/colorAccent</item>
-  </style>
-
-  <style name="SetupTheme" parent="AppTheme.NoActionBar" />
-
-  <style name="AppTheme.Button" parent="AppTheme">
-    <item name="colorButtonNormal">@android:color/background_light</item>
-  </style>
-
-  <style name="AppTheme.Button.Colored" parent="AppTheme.Button">
-    <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
-    <item name="colorButtonNormal">@color/colorAccent</item>
-  </style>
-
-  <style name="SplashTheme" parent="AppTheme.NoActionBar">
-    <item name="android:windowBackground">@drawable/bg_splash</item>
-  </style>
-</resources>
diff --git a/app/src/main/res/values/styles_widgets.xml b/app/src/main/res/values/styles_widgets.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f10b077c7d58296629c4a67f69298a5ab73e4da8
--- /dev/null
+++ b/app/src/main/res/values/styles_widgets.xml
@@ -0,0 +1,38 @@
+<resources>
+
+  <style name="Widget" />
+
+  <style name="Widget.Button" parent="Widget.AppCompat.Button">
+    <item name="backgroundTint">?attr/colorBackgroundCard</item>
+  </style>
+
+  <style name="Widget.Button.Colored" parent="Widget.AppCompat.Button.Colored" />
+
+  <style name="Widget.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
+    <item name="colorControlNormal">@color/colorFillDark</item>
+    <item name="android:textColorPrimary">@color/colorFillDark</item>
+    <item name="drawerArrowStyle">@style/Widget.DrawerArrowToggle</item>
+
+    <item name="colorFill">@color/colorFillDark</item>
+    <item name="colorOffline">@color/colorOfflineDark</item>
+    <item name="colorAway">@color/colorAwayDark</item>
+  </style>
+
+  <style name="Widget.AppBarOverlay.Light" parent="ThemeOverlay.AppCompat.ActionBar">
+    <item name="colorControlNormal">@color/colorFillLight</item>
+    <item name="android:textColorPrimary">@color/colorFillLight</item>
+    <item name="drawerArrowStyle">@style/Widget.DrawerArrowToggle.Light</item>
+
+    <item name="colorFill">@color/colorFillLight</item>
+    <item name="colorOffline">@color/colorOfflineLight</item>
+    <item name="colorAway">@color/colorAwayLight</item>
+  </style>
+
+  <style name="Widget.DrawerArrowToggle" parent="Widget.AppCompat.DrawerArrowToggle">
+    <item name="color">?attr/colorControlNormal</item>
+  </style>
+
+  <style name="Widget.DrawerArrowToggle.Light" parent="Widget.AppCompat.DrawerArrowToggle">
+    <item name="color">?attr/colorControlNormal</item>
+  </style>
+</resources>
diff --git a/app/src/main/res/values/themes_amoled.xml b/app/src/main/res/values/themes_amoled.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3b9760efea1a10b190cdba5fa39e832a2364dfd2
--- /dev/null
+++ b/app/src/main/res/values/themes_amoled.xml
@@ -0,0 +1,69 @@
+<?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="themeAmoledkName">AMOLED (Black)</string>
+  <string name="themeAmoledId">AMOLED</string>
+
+  <style name="Theme.ChatTheme.Amoled" parent="Theme.ChatTheme">
+    <item name="colorPrimary">#000</item>
+    <item name="colorPrimaryDark">#000</item>
+    <item name="colorAccent">@color/colorAccent</item>
+
+    <item name="senderColor0">#e90d7f</item>
+    <item name="senderColor1">#8e55e9</item>
+    <item name="senderColor2">#b30e0e</item>
+    <item name="senderColor3">#17b339</item>
+    <item name="senderColor4">#58afb3</item>
+    <item name="senderColor5">#9d54b3</item>
+    <item name="senderColor6">#b39775</item>
+    <item name="senderColor7">#3176b3</item>
+    <item name="senderColor8">#e90d7f</item>
+    <item name="senderColor9">#8e55e9</item>
+    <item name="senderColorA">#b30e0e</item>
+    <item name="senderColorB">#17b339</item>
+    <item name="senderColorC">#58afb3</item>
+    <item name="senderColorD">#9d54b3</item>
+    <item name="senderColorE">#b39775</item>
+    <item name="senderColorF">#3176b3</item>
+
+    <item name="colorForeground">#FFFFFF</item>
+    <item name="colorForegroundHighlight">#FFFFFF</item>
+    <item name="colorForegroundSecondary">#B3FFFFFF</item>
+    <item name="colorForegroundAction">#7986cb</item>
+    <item name="colorForegroundError">#800000</item>
+
+    <item name="colorForegroundMirc">0x0</item>
+
+    <item name="colorBackground">#000000</item>
+    <item name="android:windowBackground">@color/amoled_background</item>
+    <item name="colorBackgroundHighlight">#ff8811</item>
+    <item name="colorBackgroundSecondary">@null</item>
+    <item name="colorBackgroundCard">#303030</item>
+    <item name="colorBackgroundDialog">#000000</item>
+
+    <item name="colorTintActivity">#88cc33</item>
+    <item name="colorTintMessage">#2277dd</item>
+    <item name="colorTintHighlight">#ff8811</item>
+  </style>
+
+  <color name="amoled_background">#000000</color>
+</resources>
diff --git a/app/src/main/res/values/themes_base.xml b/app/src/main/res/values/themes_base.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1929c6d5a5bb2291628cb0523db12e4901735fe0
--- /dev/null
+++ b/app/src/main/res/values/themes_base.xml
@@ -0,0 +1,100 @@
+<resources>
+
+  <style name="Theme.AppTheme" parent="Theme.AppCompat">
+    <item name="colorPrimary">@color/colorPrimary</item>
+    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+    <item name="colorAccent">@color/colorAccent</item>
+  </style>
+
+  <style name="Theme.AppTheme.Light" parent="Theme.AppCompat.Light.DarkActionBar">
+    <item name="colorPrimary">@color/colorPrimary</item>
+    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+    <item name="colorAccent">@color/colorAccent</item>
+  </style>
+
+  <style name="Theme.AppTheme.Light.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
+    <item name="colorPrimary">@color/colorPrimary</item>
+    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+    <item name="colorAccent">@color/colorAccent</item>
+  </style>
+
+  <style name="Theme.AppTheme.NoActionBar" parent="Theme.AppCompat.NoActionBar">
+    <item name="colorPrimary">@color/colorPrimary</item>
+    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+    <item name="colorAccent">@color/colorAccent</item>
+  </style>
+
+  <style name="Theme.Base.ChatTheme" parent="Theme.AppTheme.NoActionBar" />
+
+  <style name="Theme.Base.ChatTheme.Light" parent="Theme.AppTheme.Light.NoActionBar" />
+
+  <style name="Theme.SetupTheme" parent="Theme.AppTheme.Light.NoActionBar" />
+
+  <style name="Theme.SplashTheme" parent="Theme.AppTheme.Light.NoActionBar">
+    <item name="android:windowBackground">@drawable/bg_splash</item>
+  </style>
+
+  <style name="Theme.ChatTheme" parent="Base.ChatTheme">
+    <item name="actionBarTheme">@style/Widget.AppBarOverlay</item>
+    <item name="formatBarTheme">@style/Widget.AppBarOverlay</item>
+
+    <item name="windowActionModeOverlay">true</item>
+
+    <item name="colorDivider">#1FFFFFFF</item>
+
+    <item name="colorFill">@color/colorFillDark</item>
+    <item name="colorOffline">@color/colorOfflineDark</item>
+    <item name="colorAway">@color/colorAwayDark</item>
+
+    <item name="cardStyle">@style/CardView.Dark</item>
+
+    <item name="mircColor0">#ffffff</item>
+    <item name="mircColor1">#000000</item>
+    <item name="mircColor2">#000080</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">#4169e1</item>
+    <item name="mircColorD">#ff00ff</item>
+    <item name="mircColorE">#808080</item>
+    <item name="mircColorF">#c0c0c0</item>
+  </style>
+
+  <style name="Theme.ChatTheme.Light" parent="Base.ChatTheme.Light">
+    <item name="actionBarTheme">@style/Widget.AppBarOverlay</item>
+    <item name="formatBarTheme">@style/Widget.AppBarOverlay.Light</item>
+
+    <item name="windowActionModeOverlay">true</item>
+
+    <item name="colorDivider">#1F000000</item>>
+
+    <item name="colorFill">@color/colorFillLight</item>
+    <item name="colorOffline">@color/colorOfflineLight</item>
+    <item name="colorAway">@color/colorAwayLight</item>
+
+    <item name="cardStyle">@style/CardView.Light</item>
+
+    <item name="mircColor0">#ffffff</item>
+    <item name="mircColor1">#000000</item>
+    <item name="mircColor2">#000080</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">#4169e1</item>
+    <item name="mircColorD">#ff00ff</item>
+    <item name="mircColorE">#808080</item>
+    <item name="mircColorF">#c0c0c0</item>
+  </style>
+</resources>
diff --git a/app/src/main/res/values/themes_quassel.xml b/app/src/main/res/values/themes_quassel.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2d46014a775e42e3a6b40d65e0f7a7d6a7e997a2
--- /dev/null
+++ b/app/src/main/res/values/themes_quassel.xml
@@ -0,0 +1,108 @@
+<?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="themeQuasselLightName">Quassel™ (Light)</string>
+  <string name="themeQuasselLightId">QUASSEL_LIGHT</string>
+
+  <style name="Theme.ChatTheme.Quassel_Light" parent="Theme.ChatTheme.Light">
+    <item name="senderColor0">#e90d7f</item>
+    <item name="senderColor1">#8e55e9</item>
+    <item name="senderColor2">#b30e0e</item>
+    <item name="senderColor3">#17b339</item>
+    <item name="senderColor4">#58afb3</item>
+    <item name="senderColor5">#9d54b3</item>
+    <item name="senderColor6">#b39775</item>
+    <item name="senderColor7">#3176b3</item>
+    <item name="senderColor8">#e90d7f</item>
+    <item name="senderColor9">#8e55e9</item>
+    <item name="senderColorA">#b30e0e</item>
+    <item name="senderColorB">#17b339</item>
+    <item name="senderColorC">#58afb3</item>
+    <item name="senderColorD">#9d54b3</item>
+    <item name="senderColorE">#b39775</item>
+    <item name="senderColorF">#3176b3</item>
+
+    <item name="colorForeground">#DE000000</item>
+    <item name="colorForegroundHighlight">#DE000000</item>
+    <item name="colorForegroundSecondary">#8A000000</item>
+    <item name="colorForegroundAction">#1a237e</item>
+    <item name="colorForegroundError">#800000</item>
+
+    <item name="colorForegroundMirc">0x1</item>
+
+    <item name="colorBackground">#FAFAFA</item>
+    <item name="android:windowBackground">@color/quasselLight_background</item>
+    <item name="colorBackgroundHighlight">#ff8811</item>
+    <item name="colorBackgroundSecondary">@null</item>
+    <item name="colorBackgroundCard">#FFFFFF</item>
+    <item name="colorBackgroundDialog">#FAFAFA</item>
+
+    <item name="colorTintActivity">#88cc33</item>
+    <item name="colorTintMessage">#2277dd</item>
+    <item name="colorTintHighlight">#ff8811</item>
+  </style>
+
+  <color name="quasselLight_background">#FAFAFA</color>
+
+  <string name="themeQuasselDarkName">Quassel™ (Dark)</string>
+  <string name="themeQuasselDarkId">QUASSEL_DARK</string>
+
+  <style name="Theme.ChatTheme.Quassel_Dark" parent="Theme.ChatTheme">
+    <item name="senderColor0">#e90d7f</item>
+    <item name="senderColor1">#8e55e9</item>
+    <item name="senderColor2">#b30e0e</item>
+    <item name="senderColor3">#17b339</item>
+    <item name="senderColor4">#58afb3</item>
+    <item name="senderColor5">#9d54b3</item>
+    <item name="senderColor6">#b39775</item>
+    <item name="senderColor7">#3176b3</item>
+    <item name="senderColor8">#e90d7f</item>
+    <item name="senderColor9">#8e55e9</item>
+    <item name="senderColorA">#b30e0e</item>
+    <item name="senderColorB">#17b339</item>
+    <item name="senderColorC">#58afb3</item>
+    <item name="senderColorD">#9d54b3</item>
+    <item name="senderColorE">#b39775</item>
+    <item name="senderColorF">#3176b3</item>
+
+    <item name="colorForeground">#FFFFFF</item>
+    <item name="colorForegroundHighlight">#FFFFFF</item>
+    <item name="colorForegroundSecondary">#B3FFFFFF</item>
+    <item name="colorForegroundAction">#7986cb</item>
+    <item name="colorForegroundError">#800000</item>
+
+    <item name="colorForegroundMirc">0x0</item>
+
+    <item name="colorBackground">#303030</item>
+    <item name="android:windowBackground">@color/quasselDark_background</item>
+    <item name="colorBackgroundHighlight">#ff8811</item>
+    <item name="colorBackgroundSecondary">@null</item>
+    <item name="colorBackgroundCard">#424242</item>
+    <item name="colorBackgroundDialog">#303030</item>
+
+    <item name="colorTintActivity">#88cc33</item>
+    <item name="colorTintMessage">#2277dd</item>
+    <item name="colorTintHighlight">#ff8811</item>
+  </style>
+
+  <color name="quasselDark_background">#303030</color>
+</resources>
diff --git a/app/src/main/res/values/themes_solarized.xml b/app/src/main/res/values/themes_solarized.xml
new file mode 100644
index 0000000000000000000000000000000000000000..953e2cf5f5cd8157e67230cb9e22cfc287fc3949
--- /dev/null
+++ b/app/src/main/res/values/themes_solarized.xml
@@ -0,0 +1,118 @@
+<?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="themeSolarizedLightName">Solarized (Light)</string>
+  <string name="themeSolarizedLightId">SOLARIZED_LIGHT</string>
+
+  <style name="Theme.ChatTheme.Solarized_Light" parent="Theme.ChatTheme.Light">
+    <item name="colorPrimary">?attr/colorBackgroundCard</item>
+    <item name="colorPrimaryDark">#b0ac9e</item>
+    <item name="colorAccent">#B58900</item>
+
+    <item name="actionBarTheme">@style/Widget.AppBarOverlay.Light</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="colorForeground">#839495</item>
+    <item name="colorForegroundHighlight">#839495</item>
+    <item name="colorForegroundSecondary">#576A66</item>
+    <item name="colorForegroundAction">#268BD2</item>
+    <item name="colorForegroundError">#B00000</item>
+
+    <item name="colorForegroundMirc">0xF</item>
+
+    <item name="colorBackground">#FDF6E3</item>
+    <item name="android:windowBackground">@color/solarizedLight_background</item>
+    <item name="colorBackgroundHighlight">#268bd2</item>
+    <item name="colorBackgroundSecondary">@null</item>
+    <item name="colorBackgroundCard">#EEE8D5</item>
+    <item name="colorBackgroundDialog">#FDF6E3</item>
+
+    <item name="colorTintActivity">#88cc33</item>
+    <item name="colorTintMessage">#2277dd</item>
+    <item name="colorTintHighlight">#ff8811</item>
+  </style>
+
+  <color name="solarizedLight_background">#FDF6E3</color>
+
+  <string name="themeSolarizedDarkName">Solarized (Dark)</string>
+  <string name="themeSolarizedDarkId">SOLARIZED_DARK</string>
+
+  <style name="Theme.ChatTheme.Solarized_Dark" parent="Theme.ChatTheme">
+    <item name="colorPrimary">?attr/colorBackgroundCard</item>
+    <item name="colorPrimaryDark">?attr/colorBackground</item>
+    <item name="colorAccent">#B58900</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="colorForeground">#839495</item>
+    <item name="colorForegroundHighlight">#839495</item>
+    <item name="colorForegroundSecondary">#576A66</item>
+    <item name="colorForegroundAction">#268BD2</item>
+    <item name="colorForegroundError">#B00000</item>
+
+    <item name="colorForegroundMirc">0xF</item>
+
+    <item name="colorBackground">#002B36</item>
+    <item name="android:windowBackground">@color/solarizedDark_background</item>
+    <item name="colorBackgroundHighlight">#268bd2</item>
+    <item name="colorBackgroundSecondary">@null</item>
+    <item name="colorBackgroundCard">#073642</item>
+    <item name="colorBackgroundDialog">#002B36</item>
+
+    <item name="colorTintActivity">#88cc33</item>
+    <item name="colorTintMessage">#2277dd</item>
+    <item name="colorTintHighlight">#ff8811</item>
+  </style>
+
+  <color name="solarizedDark_background">#002B36</color>
+</resources>
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializer.kt
index a0b0451e0bb8297562f5d5a6ad00e091a35b9954..41fd63f5bbb76d5e5bb6e902d914c8489e2b1dc3 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializer.kt
@@ -59,12 +59,12 @@ object DateTimeSerializer : Serializer<Temporal> {
     if (milliOfDay == -1L || julianDay == -1L)
       return Instant.EPOCH
     return when (timeSpec) {
-      TimeSpec.LocalTime     ->
+      TimeSpec.LocalTime ->
         Instant.EPOCH.atZone(ZoneOffset.systemDefault())
           .with(JulianFields.JULIAN_DAY, julianDay)
           .with(ChronoField.MILLI_OF_DAY, milliOfDay)
           .toInstant()
-      else                   ->
+      else               ->
         Instant.EPOCH.atOffset(ZoneOffset.UTC)
           .with(JulianFields.JULIAN_DAY, julianDay)
           .with(ChronoField.MILLI_OF_DAY, milliOfDay)
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
index efd3ffea182c842107e4e29e6b66b97ac3f3756b..e96c1a90b933d65a84b3b0caeecd17698a1fe52e 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
@@ -124,7 +124,7 @@ class BufferViewConfig constructor(
       _buffers.remove(bufferId)
 
     if (_temporarilyRemovedBuffers.contains(bufferId))
-      _temporarilyRemovedBuffers.remove(bufferId);
+      _temporarilyRemovedBuffers.remove(bufferId)
 
     _removedBuffers.add(bufferId)
   }
@@ -192,18 +192,18 @@ class BufferViewConfig constructor(
     super.setSortAlphabetically(sortAlphabetically)
   }
 
-  val _bufferViewId: Int = bufferViewId
-  var _bufferViewName: String = ""
-  var _networkId: NetworkId = 0
-  var _addNewBuffersAutomatically: Boolean = true
-  var _sortAlphabetically: Boolean = true
-  var _hideInactiveBuffers: Boolean = false
-  var _hideInactiveNetworks: Boolean = false
-  var _disableDecoration: Boolean = false
-  var _allowedBufferTypes: Buffer_Types = Buffer_Type.of(*Buffer_Type.validValues)
-  var _minimumActivity: Buffer_Activities = Buffer_Activities.of(0)
-  var _showSearch: Boolean = false
-  var _buffers: MutableList<BufferId> = mutableListOf()
-  var _removedBuffers: MutableSet<BufferId> = mutableSetOf()
-  var _temporarilyRemovedBuffers: MutableSet<BufferId> = mutableSetOf()
+  private val _bufferViewId: Int = bufferViewId
+  private var _bufferViewName: String = ""
+  private var _networkId: NetworkId = 0
+  private var _addNewBuffersAutomatically: Boolean = true
+  private var _sortAlphabetically: Boolean = true
+  private var _hideInactiveBuffers: Boolean = false
+  private var _hideInactiveNetworks: Boolean = false
+  private var _disableDecoration: Boolean = false
+  private var _allowedBufferTypes: Buffer_Types = Buffer_Type.of(*Buffer_Type.validValues)
+  private var _minimumActivity: Buffer_Activities = Buffer_Activities.of(0)
+  private var _showSearch: Boolean = false
+  private var _buffers: MutableList<BufferId> = mutableListOf()
+  private var _removedBuffers: MutableSet<BufferId> = mutableSetOf()
+  private var _temporarilyRemovedBuffers: MutableSet<BufferId> = mutableSetOf()
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewManager.kt
index e23d3c563319b894bfb8c27cd631c6f468d654e8..101b215a48068c5443dc781699f283a6beaf2888 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewManager.kt
@@ -3,6 +3,7 @@ package de.kuschku.libquassel.quassel.syncables
 import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.quassel.syncables.interfaces.IBufferViewManager
 import de.kuschku.libquassel.session.SignalProxy
+import io.reactivex.subjects.BehaviorSubject
 
 class BufferViewManager constructor(
   proxy: SignalProxy
@@ -35,6 +36,7 @@ class BufferViewManager constructor(
 
     proxy.synchronize(config, !initialized)
     _bufferViewConfigs[config.bufferViewId()] = config
+    bufferViewConfigIds.onNext(_bufferViewConfigs.keys)
   }
 
   override fun addBufferViewConfig(bufferViewConfigId: Int) {
@@ -49,7 +51,12 @@ class BufferViewManager constructor(
       return
 
     _bufferViewConfigs.remove(bufferViewConfigId)
+    bufferViewConfigIds.onNext(_bufferViewConfigs.keys)
   }
 
-  private val _bufferViewConfigs: MutableMap<BufferId, BufferViewConfig> = mutableMapOf()
+  private val _bufferViewConfigs: MutableMap<Int, BufferViewConfig>
+    = mutableMapOf()
+
+  val bufferViewConfigIds: BehaviorSubject<Set<Int>>
+    = BehaviorSubject.createDefault<Set<Int>>(emptySet())
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt b/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt
index 652f3dadb47f12b05aafa520cdd53855a5f32020..6ca61a86786fd2f0ce8d2eea934ec0d6089e32b5 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt
@@ -18,7 +18,6 @@ import de.kuschku.libquassel.util.helpers.hexDump
 import de.kuschku.libquassel.util.helpers.write
 import de.kuschku.libquassel.util.nio.ChainedByteBuffer
 import de.kuschku.libquassel.util.nio.WrappedChannel
-import io.reactivex.BackpressureStrategy
 import io.reactivex.subjects.BehaviorSubject
 import org.threeten.bp.ZoneOffset
 import org.threeten.bp.format.DateTimeFormatter
@@ -44,8 +43,7 @@ class CoreConnection(
   private val sizeBuffer = ByteBuffer.allocateDirect(4)
   private val chainedBuffer = ChainedByteBuffer(direct = true)
 
-  private val internalState = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED)
-  val state = internalState.toFlowable(BackpressureStrategy.LATEST)
+  val state = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED)
 
   private var channel: WrappedChannel? = null
 
@@ -61,7 +59,7 @@ class CoreConnection(
 
   fun setState(value: ConnectionState) {
     log(INFO, TAG, value.name)
-    internalState.onNext(value)
+    state.onNext(value)
   }
 
   private fun sendHandshake() {
@@ -170,7 +168,7 @@ class CoreConnection(
         }
         dataBuffer.flip()
         handlerService.parse {
-          when (internalState.value) {
+          when (state.value) {
             ConnectionState.HANDSHAKE -> processHandshake(dataBuffer)
             else                      -> processSigProxy(dataBuffer)
           }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt b/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt
index 64054b6ea97aa4cf45e4aefba47901aabeea292d..b5f4c0990ffc3cab881b2194a7ec83ea311da6cf 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt
@@ -1,19 +1,45 @@
 package de.kuschku.libquassel.session
 
-import io.reactivex.BackpressureStrategy
-import io.reactivex.Flowable
+import de.kuschku.libquassel.protocol.IdentityId
+import de.kuschku.libquassel.protocol.NetworkId
+import de.kuschku.libquassel.quassel.syncables.*
+import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 import java.io.Closeable
 
 interface ISession : Closeable {
-  val state: Flowable<ConnectionState>
+  val state: Observable<ConnectionState>
+
+  val aliasManager: AliasManager?
+  val backlogManager: BacklogManager?
+  val bufferSyncer: BufferSyncer?
+  val bufferViewManager: BufferViewManager?
+  val certManagers: Map<IdentityId, CertManager>
+  val coreInfo: CoreInfo?
+  val dccConfig: DccConfig?
+  val identities: Map<IdentityId, Identity>
+  val ignoreListManager: IgnoreListManager?
+  val ircListHelper: IrcListHelper?
+  val networks: Map<NetworkId, Network>
+  val networkConfig: NetworkConfig?
 
   companion object {
     val NULL = object : ISession {
+      override val aliasManager: AliasManager? = null
+      override val backlogManager: BacklogManager? = null
+      override val bufferSyncer: BufferSyncer? = null
+      override val bufferViewManager: BufferViewManager? = null
+      override val certManagers: Map<IdentityId, CertManager> = emptyMap()
+      override val coreInfo: CoreInfo? = null
+      override val dccConfig: DccConfig? = null
+      override val identities: Map<IdentityId, Identity> = emptyMap()
+      override val ignoreListManager: IgnoreListManager? = null
+      override val ircListHelper: IrcListHelper? = null
+      override val networks: Map<NetworkId, Network> = emptyMap()
+      override val networkConfig: NetworkConfig? = null
+
       override fun close() = Unit
-      override val state: Flowable<ConnectionState>
-        = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED)
-        .toFlowable(BackpressureStrategy.LATEST)
+      override val state = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED)
     }
   }
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
index d45a5f85d3e5d8205f3cb75c0cc9261e2b66ca38..158a82a439b4c9a29370adc308f020ff3d3e983a 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
@@ -10,7 +10,6 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.DEBUG
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO
 import de.kuschku.libquassel.util.compatibility.log
 import de.kuschku.libquassel.util.hasFlag
-import io.reactivex.Flowable
 import org.threeten.bp.Instant
 import javax.net.ssl.X509TrustManager
 
@@ -24,20 +23,20 @@ class Session(
   var coreFeatures: Quassel_Features = Quassel_Feature.NONE
 
   private val coreConnection = CoreConnection(this, address, handlerService)
-  override val state: Flowable<ConnectionState> = coreConnection.state
-
-  private var aliasManager: AliasManager? = null
-  private var backlogManager: BacklogManager? = null
-  private var bufferSyncer: BufferSyncer? = null
-  private var bufferViewManager: BufferViewManager? = null
-  private var certManagers = mutableMapOf<IdentityId, CertManager>()
-  private var coreInfo: CoreInfo? = null
-  private var dccConfig: DccConfig? = null
-  private var identities = mutableMapOf<IdentityId, Identity>()
-  private var ignoreListManager: IgnoreListManager? = null
-  private var ircListHelper: IrcListHelper? = null
-  private var networks = mutableMapOf<NetworkId, Network>()
-  private var networkConfig: NetworkConfig? = null
+  override val state = coreConnection.state
+
+  override val aliasManager = AliasManager(this)
+  override val backlogManager = BacklogManager(this)
+  override val bufferSyncer = BufferSyncer(this)
+  override val bufferViewManager = BufferViewManager(this)
+  override val certManagers = mutableMapOf<IdentityId, CertManager>()
+  override val coreInfo = CoreInfo(this)
+  override val dccConfig = DccConfig(this)
+  override val identities = mutableMapOf<IdentityId, Identity>()
+  override val ignoreListManager = IgnoreListManager(this)
+  override val ircListHelper = IrcListHelper(this)
+  override val networks = mutableMapOf<NetworkId, Network>()
+  override val networkConfig = NetworkConfig(this)
 
   init {
     coreConnection.start()
@@ -74,31 +73,14 @@ class Session(
     networks.values.forEach { syncableObject -> this.synchronize(syncableObject, true) }
     certManagers.values.forEach { syncableObject -> this.synchronize(syncableObject, true) }
 
-    aliasManager = AliasManager(this)
     synchronize(aliasManager, true)
-
-    backlogManager = BacklogManager(this)
-
-    bufferSyncer = BufferSyncer(this)
     synchronize(bufferSyncer, true)
-
-    bufferViewManager = BufferViewManager(this)
     synchronize(bufferViewManager, true)
-
-    coreInfo = CoreInfo(this)
     synchronize(coreInfo, true)
-
-    dccConfig = DccConfig(this)
     if (coreFeatures.hasFlag(QuasselFeature.DccFileTransfer))
       synchronize(dccConfig, true)
-
-    ignoreListManager = IgnoreListManager(this)
     synchronize(ignoreListManager, true)
-
-    ircListHelper = IrcListHelper(this)
     synchronize(ircListHelper, true)
-
-    networkConfig = NetworkConfig(this)
     synchronize(networkConfig, true)
 
     return true
@@ -132,16 +114,6 @@ class Session(
   override fun close() {
     coreConnection.close()
 
-    aliasManager = null
-    backlogManager = null
-    bufferSyncer = null
-    bufferViewManager = null
-    coreInfo = null
-    dccConfig = null
-    ignoreListManager = null
-    ircListHelper = null
-    networkConfig = null
-
     certManagers.clear()
     identities.clear()
     networks.clear()
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
index f2e46155289b912958b5e2bb6f3f4d03cd2c1758..a90363ffa07ebab255cac266048141097b32a96a 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
@@ -1,18 +1,47 @@
 package de.kuschku.libquassel.session
 
 import de.kuschku.libquassel.protocol.ClientData
+import de.kuschku.libquassel.protocol.IdentityId
+import de.kuschku.libquassel.protocol.NetworkId
+import de.kuschku.libquassel.quassel.syncables.*
 import de.kuschku.libquassel.quassel.syncables.interfaces.invokers.Invokers
 import de.kuschku.libquassel.util.compatibility.HandlerService
 import de.kuschku.libquassel.util.compatibility.LoggingHandler
 import de.kuschku.libquassel.util.compatibility.log
-import io.reactivex.BackpressureStrategy
-import io.reactivex.Flowable
+import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 import javax.net.ssl.X509TrustManager
 
 class SessionManager(
   private val offlineSession: ISession
-) {
+) : ISession {
+  override val aliasManager: AliasManager?
+    get() = session.or(offlineSession).aliasManager
+  override val backlogManager: BacklogManager?
+    get() = session.or(offlineSession).backlogManager
+  override val bufferSyncer: BufferSyncer?
+    get() = session.or(offlineSession).bufferSyncer
+  override val bufferViewManager: BufferViewManager?
+    get() = session.or(offlineSession).bufferViewManager
+  override val certManagers: Map<IdentityId, CertManager>
+    get() = session.or(offlineSession).certManagers
+  override val coreInfo: CoreInfo?
+    get() = session.or(offlineSession).coreInfo
+  override val dccConfig: DccConfig?
+    get() = session.or(offlineSession).dccConfig
+  override val identities: Map<IdentityId, Identity>
+    get() = session.or(offlineSession).identities
+  override val ignoreListManager: IgnoreListManager?
+    get() = session.or(offlineSession).ignoreListManager
+  override val ircListHelper: IrcListHelper?
+    get() = session.or(offlineSession).ircListHelper
+  override val networks: Map<NetworkId, Network>
+    get() = session.or(offlineSession).networks
+  override val networkConfig: NetworkConfig?
+    get() = session.or(offlineSession).networkConfig
+
+  override fun close() = session.or(offlineSession).close()
+
   init {
     log(LoggingHandler.LogLevel.INFO, "Session", "Session created")
 
@@ -37,9 +66,7 @@ class SessionManager(
   }
 
   private var inProgressSession = BehaviorSubject.createDefault(offlineSession)
-  private val inProgressSessionPublisher: Flowable<ISession>
-    = inProgressSession.toFlowable(BackpressureStrategy.LATEST)
-  val state = inProgressSessionPublisher.switchMap { it.state }
+  override val state = inProgressSession.switchMap { it.state }
   val session = state.map { connectionState ->
     if (connectionState == ConnectionState.CONNECTED)
       inProgressSession.value
@@ -47,3 +74,6 @@ class SessionManager(
       offlineSession
   }
 }
+
+fun <T> Observable<T>.or(default: T): T
+  = this.blockingLatest().firstOrNull() ?: default