diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index afa441c0176912c609b3585d0d3bafd2e04eb835..c1c6b5bb773f2799a19766f55d80b5dc4be14cf2 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -140,6 +140,7 @@ dependencies {
   implementation("commons-codec", "commons-codec", "1.12")
   implementation("com.squareup.retrofit2", "retrofit", "2.5.0")
   implementation("com.squareup.retrofit2", "converter-gson", "2.5.0")
+  implementation("com.github.pwittchen", "reactivenetwork-rx2", "3.0.2")
   withVersion("10.1.0") {
     implementation("com.jakewharton", "butterknife", version)
     kapt("com.jakewharton", "butterknife-compiler", version)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt b/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
index 1068e7be8df103d40465901ca933f2af4e26c38b..33a022c3e3e79d7cf2d81ceaf8066d09015806b5 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
@@ -19,9 +19,8 @@
 
 package de.kuschku.quasseldroid.service
 
-import de.kuschku.libquassel.connection.SocketAddress
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.util.compatibility.HandlerService
+import de.kuschku.quasseldroid.Backend
 
 class AsyncBackend(
   private val handler: HandlerService,
@@ -39,23 +38,19 @@ class AsyncBackend(
     }
   }
 
-  override fun connectUnlessConnected(address: SocketAddress, user: String, pass: String,
-                                      requireSsl: Boolean, reconnect: Boolean) {
+  override fun autoConnect(
+    ignoreConnectionState: Boolean,
+    ignoreSetting: Boolean,
+    ignoreErrors: Boolean,
+    connectionInfo: Backend.ConnectionInfo?
+  ) {
     handler.backend {
-      backend.connectUnlessConnected(address, user, pass, requireSsl, reconnect)
-    }
-  }
-
-  override fun connect(address: SocketAddress, user: String, pass: String, requireSsl: Boolean,
-                       reconnect: Boolean) {
-    handler.backend {
-      backend.connect(address, user, pass, requireSsl, reconnect)
-    }
-  }
-
-  override fun reconnect() {
-    handler.backend {
-      backend.reconnect()
+      backend.autoConnect(
+        ignoreConnectionState,
+        ignoreSetting,
+        ignoreErrors,
+        connectionInfo
+      )
     }
   }
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt b/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt
index 40bfc7d69098384ce1c63fe1feede7e6057c3638..cdbfe21cf7c6e572933ec8057fead9e59a80568c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt
@@ -26,7 +26,7 @@ import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.DEBUG
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.persistence.dao.findFirstByBufferId
 import de.kuschku.quasseldroid.persistence.dao.get
 import de.kuschku.quasseldroid.persistence.db.AccountDatabase
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselBinder.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselBinder.kt
index d4d7d450c3acce722a4573a6bcf42433254ffe8c..05a2a5dc3f5f86decbffa3c6e16dcf79edcbe409 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselBinder.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselBinder.kt
@@ -20,6 +20,6 @@
 package de.kuschku.quasseldroid.service
 
 import android.os.Binder
-import de.kuschku.libquassel.session.Backend
+import de.kuschku.quasseldroid.Backend
 
 class QuasselBinder(val backend: Backend) : Binder()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
index dba7e5d4fd337288add47c49187753d2c7801d22..03a89ce319263d771385d80bf7ac38b4ecb38182 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
@@ -31,7 +31,8 @@ import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.session.NotificationManager
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.libquassel.util.helpers.clampOf
+import de.kuschku.libquassel.util.helper.clampOf
+import de.kuschku.libquassel.util.helper.or
 import de.kuschku.libquassel.util.irc.HostmaskHelper
 import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.GlideApp
@@ -259,7 +260,7 @@ class QuasselNotificationBackend @Inject constructor(
             this.showNotification(buffer)
           }
         },
-        clampOf(session.lag.value * 3 + 100, 16, 3_000),
+        clampOf(session.lag.or(0) * 3 + 100, 16, 3_000),
         TimeUnit.MILLISECONDS
       )
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
index bf557b57d9cfa2982521249acfb0eca543124018..ba8068b5a98f389338bf95b15c2402f5fbbd4039 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
@@ -19,11 +19,14 @@
 
 package de.kuschku.quasseldroid.service
 
-import android.content.*
-import android.net.ConnectivityManager
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
 import android.text.SpannableString
 import androidx.core.app.RemoteInput
 import androidx.lifecycle.Observer
+import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
 import de.kuschku.libquassel.connection.ConnectionState
 import de.kuschku.libquassel.connection.HostnameVerifier
 import de.kuschku.libquassel.connection.SocketAddress
@@ -31,16 +34,16 @@ import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.quassel.QuasselFeatures
 import de.kuschku.libquassel.quassel.syncables.interfaces.IAliasManager
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.session.Session
 import de.kuschku.libquassel.session.SessionManager
-import de.kuschku.libquassel.util.compatibility.LoggingHandler
+import de.kuschku.libquassel.session.manager.ConnectionInfo
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO
-import de.kuschku.libquassel.util.helpers.clampOf
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.clampOf
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.malheur.CrashHandler
+import de.kuschku.quasseldroid.Backend
 import de.kuschku.quasseldroid.BuildConfig
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.R
@@ -64,9 +67,7 @@ import de.kuschku.quasseldroid.util.compatibility.AndroidHandlerService
 import de.kuschku.quasseldroid.util.helper.*
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatSerializer
 import de.kuschku.quasseldroid.util.ui.LocaleHelper
-import io.reactivex.subjects.PublishSubject
 import org.threeten.bp.Instant
-import java.util.concurrent.TimeUnit
 import javax.inject.Inject
 import javax.net.ssl.X509TrustManager
 
@@ -117,12 +118,14 @@ class QuasselService : DaggerLifecycleService(),
           backendImplementation.disconnect(true)
           stopSelf()
         } else {
-          backendImplementation.connectUnlessConnected(
-            SocketAddress(account.host, account.port),
-            account.user,
-            account.pass,
-            account.requireSsl,
-            true
+          backendImplementation.autoConnect(
+            connectionInfo = Backend.ConnectionInfo(
+              SocketAddress(account.host, account.port),
+              account.user,
+              account.pass,
+              account.requireSsl,
+              true
+            )
           )
         }
       }
@@ -185,7 +188,7 @@ class QuasselService : DaggerLifecycleService(),
           it.toString() to ircFormatSerializer.toEscapeCodes(SpannableString(it))
         }
 
-        sessionManager.session.value?.let { session ->
+        sessionManager.connectedSession.value?.let { session ->
           session.bufferSyncer.bufferInfo(bufferId)?.also { bufferInfo ->
             val output = mutableListOf<IAliasManager.Command>()
             for ((_, formatted) in lines) {
@@ -203,15 +206,17 @@ class QuasselService : DaggerLifecycleService(),
     } else {
       val clearMessageId = MsgId(intent.getLongExtra("mark_read_message", -1))
       if (bufferId.isValidId() && clearMessageId.isValidId()) {
-        sessionManager.session.value?.bufferSyncer?.requestSetLastSeenMsg(bufferId, clearMessageId)
-        sessionManager.session.value?.bufferSyncer?.requestMarkBufferAsRead(bufferId)
+        sessionManager.connectedSession.value?.bufferSyncer?.requestSetLastSeenMsg(bufferId,
+                                                                                   clearMessageId)
+        sessionManager.connectedSession.value?.bufferSyncer?.requestMarkBufferAsRead(bufferId)
       }
 
       val hideMessageId = MsgId(intent.getLongExtra("hide_message", -1))
       if (bufferId.isValidId() && hideMessageId.isValidId()) {
         if (notificationSettings.markReadOnSwipe) {
-          sessionManager.session.value?.bufferSyncer?.requestSetLastSeenMsg(bufferId, hideMessageId)
-          sessionManager.session.value?.bufferSyncer?.requestMarkBufferAsRead(bufferId)
+          sessionManager.connectedSession.value?.bufferSyncer?.requestSetLastSeenMsg(bufferId,
+                                                                                     hideMessageId)
+          sessionManager.connectedSession.value?.bufferSyncer?.requestMarkBufferAsRead(bufferId)
         } else {
           handlerService.backend {
             database.notifications().markHidden(bufferId, hideMessageId)
@@ -277,36 +282,32 @@ class QuasselService : DaggerLifecycleService(),
 
     override fun sessionManager() = service?.sessionManager
 
-    override fun connectUnlessConnected(address: SocketAddress, user: String, pass: String,
-                                        requireSsl: Boolean, reconnect: Boolean) {
+    override fun autoConnect(
+      ignoreConnectionState: Boolean,
+      ignoreSetting: Boolean,
+      ignoreErrors: Boolean,
+      connectionInfo: Backend.ConnectionInfo?
+    ) {
       service?.apply {
-        sessionManager.ifDisconnected {
-          connect(address, user, pass, requireSsl, reconnect)
-        }
-      }
-    }
-
-    override fun connect(address: SocketAddress, user: String, pass: String, requireSsl: Boolean,
-                         reconnect: Boolean) {
-      service?.apply {
-        disconnect()
-        sessionManager.connect(
-          SessionManager.ConnectionInfo(
-            clientData = clientData,
-            trustManager = trustManager,
-            hostnameVerifier = hostnameVerifier,
-            address = address,
-            userData = Pair(user, pass),
-            requireSsl = requireSsl,
-            shouldReconnect = reconnect
+        if (connectionInfo != null) {
+          sessionManager.autoConnect(
+            ignoreConnectionState,
+            ignoreSetting,
+            ignoreErrors,
+            ConnectionInfo(
+              clientData = clientData,
+              trustManager = trustManager,
+              hostnameVerifier = hostnameVerifier,
+              address = connectionInfo.address,
+              userData = Pair(connectionInfo.username,
+                              connectionInfo.password),
+              requireSsl = connectionInfo.requireSsl,
+              shouldReconnect = connectionInfo.shouldReconnect
+            )
           )
-        )
-      }
-    }
-
-    override fun reconnect() {
-      service?.apply {
-        sessionManager.reconnect()
+        } else {
+          sessionManager.autoConnect(ignoreConnectionState, ignoreSetting, ignoreErrors)
+        }
       }
     }
 
@@ -318,8 +319,8 @@ class QuasselService : DaggerLifecycleService(),
 
     override fun requestConnectNewNetwork() {
       service?.apply {
-        sessionManager.session.flatMap(ISession::liveNetworkAdded).firstElement().flatMap { id ->
-          sessionManager.session.flatMap(ISession::liveNetworks)
+        sessionManager.connectedSession.flatMap(ISession::liveNetworkAdded).firstElement().flatMap { id ->
+          sessionManager.connectedSession.flatMap(ISession::liveNetworks)
             .map { it[id] }
             .flatMap { network ->
               network.liveInitialized
@@ -345,18 +346,6 @@ class QuasselService : DaggerLifecycleService(),
   @Inject
   lateinit var accountDatabase: AccountDatabase
 
-  class CustomConnectivityReceiver : BroadcastReceiver() {
-    override fun onReceive(context: Context?, intent: Intent?) {
-      if (context != null && intent != null) {
-        connectivity.onNext(Unit)
-      }
-    }
-
-    val connectivity = PublishSubject.create<Unit>()
-  }
-
-  private val connectivityReceiver = CustomConnectivityReceiver()
-
   private fun disconnectFromCore() {
     getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE).editCommit {
       putBoolean(Keys.Status.reconnect, false)
@@ -413,14 +402,17 @@ class QuasselService : DaggerLifecycleService(),
       }
     })
 
-    connectivityReceiver.connectivity
-      .delay(200, TimeUnit.MILLISECONDS)
-      .throttleFirst(1, TimeUnit.SECONDS)
+    ReactiveNetwork
+      .observeNetworkConnectivity(applicationContext)
       .toLiveData()
-      .observe(this, Observer {
+      .observe(this, Observer { connectivity ->
+        log(INFO, "QuasselService", "Connectivity changed: $connectivity")
         handlerService.backend {
-          LoggingHandler.log(INFO, "QuasselService", "Autoreconnect: Network changed")
-          sessionManager.autoReconnect(true)
+          log(INFO, "QuasselService", "Reconnect triggered: Network changed")
+          sessionManager.autoConnect(
+            ignoreConnectionState = true,
+            ignoreSetting = true
+          )
         }
       })
 
@@ -448,8 +440,6 @@ class QuasselService : DaggerLifecycleService(),
       registerOnSharedPreferenceChangeListener(this@QuasselService)
     }
 
-    registerReceiver(connectivityReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
-
     notificationManager.init()
 
     update()
@@ -467,7 +457,7 @@ class QuasselService : DaggerLifecycleService(),
         scheduled = false
 
         backoff = clampOf(backoff * 2, BACKOFF_MIN, BACKOFF_MAX)
-        sessionManager.autoReconnect(true)
+        sessionManager.autoConnect(ignoreSetting = true)
       }
     }
   }
@@ -480,8 +470,6 @@ class QuasselService : DaggerLifecycleService(),
       unregisterOnSharedPreferenceChangeListener(this@QuasselService)
     }
 
-    unregisterReceiver(connectivityReceiver)
-
     sessionManager.dispose()
     asyncBackend.setDisconnectCallback(null)
     backendImplementation.service = null
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
index 0b964f74867619125569554be096ae8f721b2311..186750118a445ae40ed648a024ddddb63c421ebf 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt
@@ -56,12 +56,16 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.PortDefaults.
 import de.kuschku.libquassel.session.Error
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.Optional
+import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
+import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO
 import de.kuschku.libquassel.util.flag.and
 import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.libquassel.util.flag.minus
 import de.kuschku.libquassel.util.flag.or
-import de.kuschku.libquassel.util.helpers.nullIf
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.invoke
+import de.kuschku.libquassel.util.helper.nullIf
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.DefaultNetworkServer
@@ -206,7 +210,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
 
           val forceJoin = intent.getBooleanExtra(KEY_FORCE_JOIN, false)
 
-          modelHelper.session.filter(Optional<ISession>::isPresent).firstElement().subscribe {
+          modelHelper.connectedSession.filter(Optional<ISession>::isPresent).firstElement().subscribe {
             it.orNull()?.also { session ->
               val info = session.bufferSyncer.find(
                 bufferName = channel,
@@ -249,7 +253,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
 
           val forceJoin = intent.getBooleanExtra(KEY_FORCE_JOIN, false)
 
-          modelHelper.session.filter(Optional<ISession>::isPresent).firstElement().subscribe {
+          modelHelper.connectedSession.filter(Optional<ISession>::isPresent).firstElement().subscribe {
             it.orNull()?.also { session ->
               val info = session.bufferSyncer.find(
                 bufferName = channel,
@@ -465,7 +469,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
     modelHelper.errors.toLiveData(BackpressureStrategy.BUFFER).observe(this, Observer { error ->
       error?.let {
         when (it) {
-          is Error.HandshakeError -> it.message.let {
+          is Error.HandshakeError  -> it.message.let {
             when (it) {
               is HandshakeMessage.ClientInitAck     ->
                 if (it.coreConfigured == false)
@@ -530,7 +534,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                               val user = userField.text.toString()
                               val pass = passField.text.toString()
 
-                              backend.value.orNull()?.updateUserDataAndLogin(user, pass)
+                              backend.value?.orNull()?.updateUserDataAndLogin(user, pass)
                             }
                           }
                           .titleColorAttr(R.attr.colorTextPrimary)
@@ -555,7 +559,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                   .show()
             }
           }
-          is Error.SslError       -> {
+          is Error.SslError        -> {
             it.exception.let {
               if (it == QuasselSecurityException.NoSsl) {
                 // Ssl is required but not available
@@ -616,7 +620,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                             )
 
                             runOnUiThread {
-                              backend.value.orNull()?.reconnect()
+                              log(INFO, "ChatActivity", "Reconnect triggered: User action")
+                              backend.value?.orNull()?.autoConnect(ignoreErrors = true)
                             }
                           }
                         }
@@ -661,7 +666,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                             }
 
                             runOnUiThread {
-                              backend.value.orNull()?.reconnect()
+                              log(INFO, "ChatActivity", "Reconnect triggered: User action")
+                              backend.value?.orNull()?.autoConnect(ignoreErrors = true)
                             }
                           }
                         }
@@ -699,7 +705,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
                             )
 
                             runOnUiThread {
-                              backend.value.orNull()?.reconnect()
+                              log(INFO, "ChatActivity", "Reconnect triggered: User action")
+                              backend.value?.orNull()?.autoConnect(ignoreErrors = true)
                             }
                           }
                         }
@@ -714,51 +721,49 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
               }
             }
           }
-        }
-      }
-    })
-
-    // Connection errors that should show up as toast
-    modelHelper.connectionErrors.toLiveData().observe(this, Observer { error ->
-      error?.let {
-        val cause = it.cause
-        when {
-          it is UnknownHostException         -> {
-            val host = it.message?.replace("Host is unresolved: ", "")
-
-            Toast.makeText(this,
-                           getString(R.string.label_error_unknown_host, host),
-                           Toast.LENGTH_LONG).show()
-          }
-          it is ProtocolVersionException     -> {
-            Toast.makeText(this,
-                           getString(R.string.label_error_invalid_protocol_version,
-                                     it.protocol.version.toInt()),
-                           Toast.LENGTH_LONG).show()
-          }
-          it is ConnectException &&
-          cause is libcore.io.ErrnoException -> {
-            val errorCode = OsConstants.errnoName(cause.errno)
-            val errorName = OsConstants.strerror(cause.errno)
-
-            Toast.makeText(this,
-                           getString(R.string.label_error_connection, errorName, errorCode),
-                           Toast.LENGTH_LONG).show()
-          }
-          it is ConnectException &&
-          Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
-          cause is ErrnoException            -> {
-            val errorCode = OsConstants.errnoName(cause.errno)
-            val errorName = OsConstants.strerror(cause.errno)
-
-            Toast.makeText(this,
-                           getString(R.string.label_error_connection, errorName, errorCode),
-                           Toast.LENGTH_LONG).show()
-          }
-          else                               -> {
-            Toast.makeText(this,
-                           getString(R.string.label_error_connection_closed),
-                           Toast.LENGTH_LONG).show()
+          is Error.ConnectionError -> {
+            it.throwable.let {
+              val cause = it.cause
+              when {
+                it is UnknownHostException         -> {
+                  val host = it.message?.replace("Host is unresolved: ", "")
+
+                  Toast.makeText(this,
+                                 getString(R.string.label_error_unknown_host, host),
+                                 Toast.LENGTH_LONG).show()
+                }
+                it is ProtocolVersionException     -> {
+                  Toast.makeText(this,
+                                 getString(R.string.label_error_invalid_protocol_version,
+                                           it.protocol.version.toInt()),
+                                 Toast.LENGTH_LONG).show()
+                }
+                it is ConnectException &&
+                cause is libcore.io.ErrnoException -> {
+                  val errorCode = OsConstants.errnoName(cause.errno)
+                  val errorName = OsConstants.strerror(cause.errno)
+
+                  Toast.makeText(this,
+                                 getString(R.string.label_error_connection, errorName, errorCode),
+                                 Toast.LENGTH_LONG).show()
+                }
+                it is ConnectException &&
+                Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
+                cause is ErrnoException            -> {
+                  val errorCode = OsConstants.errnoName(cause.errno)
+                  val errorName = OsConstants.strerror(cause.errno)
+
+                  Toast.makeText(this,
+                                 getString(R.string.label_error_connection, errorName, errorCode),
+                                 Toast.LENGTH_LONG).show()
+                }
+                else                               -> {
+                  Toast.makeText(this,
+                                 getString(R.string.label_error_connection_closed),
+                                 Toast.LENGTH_LONG).show()
+                }
+              }
+            }
           }
         }
       }
@@ -777,7 +782,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
             drawerLayout.openDrawer(GravityCompat.START)
           }
           connectedAccount = accountId
-          modelHelper.session.value?.orNull()?.let { session ->
+          modelHelper.connectedSession.value?.orNull()?.let { session ->
             if (session.identities.isEmpty()) {
               UserSetupActivity.launch(this)
             }
@@ -808,9 +813,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
 
     connectionStatusDisplay.setOnClickListener {
       modelHelper.sessionManager.value?.orNull()?.apply {
-        ifDisconnected {
-          autoReconnect()
-        }
+        log(INFO, "ChatActivity", "Reconnect triggered: User action")
+        backend.value?.orNull()?.autoConnect(ignoreErrors = true, ignoreSetting = true)
       }
     }
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt
index 55a290928eef8fbda78ae9b507fe499bdcffd9aa..d07e81af14423e724ae7da30ff33e3532cb8a14f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt
@@ -31,7 +31,8 @@ import butterknife.ButterKnife
 import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.GlideApp
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AppearanceSettings
@@ -40,7 +41,10 @@ import de.kuschku.quasseldroid.ui.info.channel.ChannelInfoActivity
 import de.kuschku.quasseldroid.ui.info.user.UserInfoActivity
 import de.kuschku.quasseldroid.util.ColorContext
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
-import de.kuschku.quasseldroid.util.helper.*
+import de.kuschku.quasseldroid.util.helper.loadAvatars
+import de.kuschku.quasseldroid.util.helper.setTooltip
+import de.kuschku.quasseldroid.util.helper.toLiveData
+import de.kuschku.quasseldroid.util.helper.visibleIf
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
 import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
 import de.kuschku.quasseldroid.util.ui.SpanFormatter
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/create/ChannelCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/create/ChannelCreateFragment.kt
index a9d464267d3d7e47f0f27f0d3bc12d2918b9af54..a4cbde6d30e468f69681cb5bb3575b6ccc016fa6 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/create/ChannelCreateFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/create/ChannelCreateFragment.kt
@@ -35,13 +35,13 @@ import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.syncables.IrcChannel
 import de.kuschku.libquassel.quassel.syncables.Network
-import de.kuschku.libquassel.util.helpers.nullIf
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.nullIf
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.ui.chat.ChatActivity
 import de.kuschku.quasseldroid.ui.chat.add.NetworkAdapter
 import de.kuschku.quasseldroid.ui.chat.add.NetworkItem
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.setDependent
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
@@ -158,7 +158,7 @@ class ChannelCreateFragment : ServiceBoundSettingsFragment() {
               networkId = selectedNetworkId,
               type = Buffer_Type.of(Buffer_Type.StatusBuffer)
             )?.let { statusBuffer ->
-              modelHelper.session.value?.orNull()?.rpcHandler?.apply {
+              modelHelper.connectedSession.value?.orNull()?.rpcHandler?.apply {
                 sendInput(statusBuffer, "/join $channelName")
               }
             }
@@ -175,7 +175,7 @@ class ChannelCreateFragment : ServiceBoundSettingsFragment() {
             networkId = selectedNetworkId,
             type = Buffer_Type.of(Buffer_Type.StatusBuffer)
           )?.let { statusBuffer ->
-            modelHelper.session.value?.orNull()?.rpcHandler?.apply {
+            modelHelper.connectedSession.value?.orNull()?.rpcHandler?.apply {
               sendInput(statusBuffer, "/join $channelName")
               modelHelper.networks.switchMap {
                 it[selectedNetworkId]?.liveIrcChannel(channelName)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/join/ChannelJoinFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/join/ChannelJoinFragment.kt
index 4c6d13f738587200511780b36daa13c59dcc5bb5..eb48e212188bad47026db7f3516b93899006d5fb 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/join/ChannelJoinFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/join/ChannelJoinFragment.kt
@@ -32,11 +32,11 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.syncables.Network
+import de.kuschku.libquassel.util.helper.combineLatest
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.ui.chat.ChatActivity
 import de.kuschku.quasseldroid.ui.chat.add.NetworkAdapter
 import de.kuschku.quasseldroid.ui.chat.add.NetworkItem
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
 import de.kuschku.quasseldroid.viewmodel.helper.QuasselViewModelHelper
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/query/QueryCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/query/QueryCreateFragment.kt
index 83af1433ce4bd29e4bbf2cd91d4c5d9cbdfee35c..297d261e3f622776b8cb45df4e763e37e111a62c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/query/QueryCreateFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/add/query/QueryCreateFragment.kt
@@ -47,8 +47,9 @@ import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.syncables.IrcUser
 import de.kuschku.libquassel.quassel.syncables.Network
 import de.kuschku.libquassel.util.Optional
-import de.kuschku.libquassel.util.helpers.mapOrElse
-import de.kuschku.libquassel.util.helpers.mapSwitchMap
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.mapOrElse
+import de.kuschku.libquassel.util.helper.mapSwitchMap
 import de.kuschku.libquassel.util.irc.IrcCaseMappers
 import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.GlideApp
@@ -60,7 +61,6 @@ import de.kuschku.quasseldroid.ui.chat.add.NetworkItem
 import de.kuschku.quasseldroid.ui.chat.nicks.NickListAdapter
 import de.kuschku.quasseldroid.util.ColorContext
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.loadWithFallbacks
 import de.kuschku.quasseldroid.util.helper.styledAttributes
 import de.kuschku.quasseldroid.util.helper.toLiveData
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt
index 5b7e320093ff8fc7f719e7359ed1ca5a0384b786..e5ffbc30229332121970a26fb82cbd681fa374db 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt
@@ -49,10 +49,7 @@ import de.kuschku.libquassel.quassel.syncables.BufferViewConfig
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.libquassel.util.flag.minus
-import de.kuschku.libquassel.util.helpers.mapMap
-import de.kuschku.libquassel.util.helpers.mapOrElse
-import de.kuschku.libquassel.util.helpers.nullIf
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.*
 import de.kuschku.quasseldroid.BuildConfig
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.persistence.db.AccountDatabase
@@ -68,7 +65,10 @@ import de.kuschku.quasseldroid.ui.coresettings.network.NetworkEditActivity
 import de.kuschku.quasseldroid.ui.info.channellist.ChannelListActivity
 import de.kuschku.quasseldroid.util.ColorContext
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
-import de.kuschku.quasseldroid.util.helper.*
+import de.kuschku.quasseldroid.util.helper.setTooltip
+import de.kuschku.quasseldroid.util.helper.styledAttributes
+import de.kuschku.quasseldroid.util.helper.toLiveData
+import de.kuschku.quasseldroid.util.helper.visibleIf
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
 import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
 import de.kuschku.quasseldroid.util.ui.view.WarningBarView
@@ -128,7 +128,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
     override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
       val selected = modelHelper.selectedBuffer.value
       val info = selected?.info
-      val session = modelHelper.session.value?.orNull()
+      val session = modelHelper.connectedSession.value?.orNull()
       val bufferSyncer = session?.bufferSyncer
       val network = session?.networks?.get(selected?.info?.networkId)
       val bufferViewConfig = modelHelper.bufferViewConfig.value
@@ -274,7 +274,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
     var hasSetBufferViewConfigId = false
     adapter.setOnUpdateFinishedListener {
       if (!hasSetBufferViewConfigId) {
-        chatListSpinner.setSelection(adapter.indexOf(modelHelper.chat.bufferViewConfigId.value).nullIf { it == -1 }
+        chatListSpinner.setSelection(adapter.indexOf(modelHelper.chat.bufferViewConfigId.or(-1)).nullIf { it == -1 }
                                      ?: 0)
         modelHelper.chat.bufferViewConfigId.onNext(chatListSpinner.selectedItemId.toInt())
         hasSetBufferViewConfigId = true
@@ -486,11 +486,13 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
     })
 
     chatListToolbar.inflateMenu(R.menu.context_bufferlist)
-    chatListToolbar.menu.findItem(R.id.action_search).isChecked = modelHelper.chat.bufferSearchTemporarilyVisible.value
+    chatListToolbar.menu.findItem(R.id.action_search).isChecked = modelHelper.chat.bufferSearchTemporarilyVisible.or(
+      false)
     chatListToolbar.setOnMenuItemClickListener { item ->
       when (item.itemId) {
         R.id.action_archived_chats -> {
-          ArchiveActivity.launch(requireContext(), chatlistId = modelHelper.chat.bufferViewConfigId.value)
+          ArchiveActivity.launch(requireContext(),
+                                 chatlistId = modelHelper.chat.bufferViewConfigId.or(-1))
           true
         }
         R.id.action_search      -> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt
index 6d2853800ca567a597d9c6c6a9ccc37bda2f4621..bf7d2e0db507761e59caddf4ffe0d42769c5b1ac 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt
@@ -33,8 +33,8 @@ import de.kuschku.libquassel.quassel.syncables.Network
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.libquassel.util.helpers.nullIf
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.nullIf
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/ChatlineFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/ChatlineFragment.kt
index 10c866aff8f9570d8269f984d66003d3d2ed68ae..b42092275c22e0fe9ac5411c9d2120beb0eaff9d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/ChatlineFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/ChatlineFragment.kt
@@ -34,6 +34,7 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import de.kuschku.libquassel.quassel.syncables.interfaces.IAliasManager
+import de.kuschku.libquassel.util.helper.invoke
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
@@ -181,7 +182,7 @@ class ChatlineFragment : ServiceBoundFragment() {
         for ((stripped, _) in lines) {
           modelHelper.chat.addRecentlySentMessage(stripped)
         }
-        modelHelper.session { sessionOptional ->
+        modelHelper.connectedSession { sessionOptional ->
           val session = sessionOptional.orNull()
           modelHelper.chat.bufferId { bufferId ->
             session?.bufferSyncer?.bufferInfo(bufferId)?.also { bufferInfo ->
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
index 554da02b7268a2179a5c6d6936c9cb5a206fea97..a4b21fc9a54b841594686dc2800bedd982772f16 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt
@@ -49,9 +49,7 @@ import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.quassel.syncables.BufferSyncer
 import de.kuschku.libquassel.session.SessionManager
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.libquassel.util.helpers.mapSwitchMap
-import de.kuschku.libquassel.util.helpers.nullIf
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.*
 import de.kuschku.libquassel.util.irc.HostmaskHelper
 import de.kuschku.quasseldroid.GlideApp
 import de.kuschku.quasseldroid.R
@@ -131,8 +129,8 @@ class MessageListFragment : ServiceBoundFragment() {
   private val actionModeCallback = object : ActionMode.Callback {
     override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?) = when (item?.itemId) {
       R.id.action_user_info -> {
-        modelHelper.chat.selectedMessages.value.values.firstOrNull()?.let { msg ->
-          modelHelper.session.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
+        modelHelper.chat.selectedMessages.value?.values?.firstOrNull()?.let { msg ->
+          modelHelper.connectedSession.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
             modelHelper.bufferData.value?.info?.let(BufferInfo::networkId)?.let { networkId ->
               UserInfoActivity.launch(
                 requireContext(),
@@ -153,7 +151,7 @@ class MessageListFragment : ServiceBoundFragment() {
       }
       R.id.action_copy      -> {
         val builder = SpannableStringBuilder()
-        modelHelper.chat.selectedMessages.value.values.asSequence().sortedBy {
+        modelHelper.chat.selectedMessages.value?.values.orEmpty().asSequence().sortedBy {
           it.original.messageId
         }.map {
           if (it.name != null && it.content != null) {
@@ -182,7 +180,7 @@ class MessageListFragment : ServiceBoundFragment() {
       }
       R.id.action_share     -> {
         val builder = SpannableStringBuilder()
-        modelHelper.chat.selectedMessages.value.values.asSequence().sortedBy {
+        modelHelper.chat.selectedMessages.value?.values.orEmpty().asSequence().sortedBy {
           it.original.messageId
         }.map {
           if (it.name != null && it.content != null) {
@@ -252,7 +250,7 @@ class MessageListFragment : ServiceBoundFragment() {
     linearLayoutManager = LinearLayoutManager(context)
     linearLayoutManager.reverseLayout = true
 
-    backlogRequester = BacklogRequester(modelHelper.session, database, accountDatabase)
+    backlogRequester = BacklogRequester(modelHelper.connectedSession, database, accountDatabase)
 
     adapter.setOnClickListener { msg ->
       if (actionMode != null) {
@@ -262,7 +260,7 @@ class MessageListFragment : ServiceBoundFragment() {
           else -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
         }
       } else if (msg.hasSpoilers) {
-        val value = modelHelper.chat.expandedMessages.value
+        val value = modelHelper.chat.expandedMessages.value.orEmpty()
         modelHelper.chat.expandedMessages.onNext(
           if (value.contains(msg.original.messageId)) value - msg.original.messageId
           else value + msg.original.messageId
@@ -288,7 +286,7 @@ class MessageListFragment : ServiceBoundFragment() {
         )
       }
     adapter.setOnSenderIconClickListener { msg ->
-      modelHelper.session.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
+      modelHelper.connectedSession.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
         modelHelper.bufferData.value?.info?.let(BufferInfo::networkId)?.let { networkId ->
           UserInfoActivity.launch(
             requireContext(),
@@ -424,7 +422,7 @@ class MessageListFragment : ServiceBoundFragment() {
       }
     })
 
-    modelHelper.session.toLiveData().zip(lastMessageId).observe(
+    modelHelper.connectedSession.toLiveData().zip(lastMessageId).observe(
       this, Observer {
       runInBackground {
         val session = it?.first?.orNull()
@@ -508,7 +506,7 @@ class MessageListFragment : ServiceBoundFragment() {
                      ?: BufferId(-1)
         if (buffer != lastBuffer) {
           adapter.clearCache()
-          modelHelper.session.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
+          modelHelper.connectedSession.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
             onBufferChange(lastBuffer, buffer, firstVisibleMessageId, bufferSyncer)
           }
           lastBuffer = buffer
@@ -557,7 +555,7 @@ class MessageListFragment : ServiceBoundFragment() {
     val previous = lastBuffer
     val firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition()
     val messageId = adapter[firstVisibleItemPosition]?.content?.messageId
-    val bufferSyncer = modelHelper.session.value?.orNull()?.bufferSyncer
+    val bufferSyncer = modelHelper.connectedSession.value?.orNull()?.bufferSyncer
     if (previous != null && messageId != null) {
       bufferSyncer?.requestSetMarkerLine(previous, messageId)
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListAdapter.kt
index 81d95bc2e23fbfa70db878eb0ed96a7f007b0bf5..9cfc6aa62e20f6f4c29bbd1aa6bae74e965ede03 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListAdapter.kt
@@ -30,7 +30,7 @@ import androidx.recyclerview.widget.RecyclerView
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.libquassel.protocol.NetworkId
-import de.kuschku.libquassel.util.helpers.nullIf
+import de.kuschku.libquassel.util.helper.nullIf
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.util.helper.letIf
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt
index 2b81e90ff6519006fca863fded80ef24e0bc3697..33c954764bf82dc0a4b643fc06265ee3d7c8876c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt
@@ -40,7 +40,7 @@ import com.bumptech.glide.util.FixedPreloadSizeProvider
 import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.BufferInfo
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.libquassel.util.irc.IrcCaseMappers
 import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.GlideApp
@@ -193,7 +193,7 @@ class NickListFragment : ServiceBoundFragment() {
   }
 
   private val clickListener: ((NetworkId, String) -> Unit) = { networkId, nick ->
-    modelHelper.session.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
+    modelHelper.connectedSession.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
       UserInfoActivity.launch(
         requireContext(),
         openBuffer = false,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt
index 4684d62115c9e9ba2199109e2206d8d998899165..6618e7f37ceeca71057f6c435ab47bdd96ad5726 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt
@@ -31,12 +31,12 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import de.kuschku.libquassel.protocol.BufferId
+import de.kuschku.libquassel.util.helper.invoke
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.ui.chat.input.*
-import de.kuschku.quasseldroid.util.helper.invoke
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatSerializer
@@ -128,7 +128,7 @@ class TopicFragment : ServiceBoundSettingsFragment(), Savable {
   }
 
   override fun onSave(): Boolean {
-    modelHelper.session { sessionOptional ->
+    modelHelper.connectedSession { sessionOptional ->
       val session = sessionOptional.orNull()
       modelHelper.chat.bufferId { bufferId ->
         session?.bufferSyncer?.bufferInfo(bufferId)?.also { bufferInfo ->
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt
index b426457dfcc6765911d9ac311d0b956f4a7a8ff1..a48dd1ebea5e3f13303f4976f0cc3eaf63fe6c42 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt
@@ -36,6 +36,7 @@ import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.syncables.BufferViewConfig
 import de.kuschku.libquassel.quassel.syncables.Identity
 import de.kuschku.libquassel.quassel.syncables.Network
+import de.kuschku.libquassel.util.helper.combineLatest
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.ui.coresettings.aliaslist.AliasListActivity
 import de.kuschku.quasseldroid.ui.coresettings.chatlist.ChatlistCreateActivity
@@ -49,7 +50,6 @@ import de.kuschku.quasseldroid.ui.coresettings.network.NetworkEditActivity
 import de.kuschku.quasseldroid.ui.coresettings.networkconfig.NetworkConfigActivity
 import de.kuschku.quasseldroid.ui.coresettings.passwordchange.PasswordChangeActivity
 import de.kuschku.quasseldroid.ui.info.core.CoreInfoActivity
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.helper.visibleIf
 import de.kuschku.quasseldroid.util.missingfeatures.MissingFeature
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
index 466153b14d62ba171c90059ef2b66a2288e1295e..6d86850c887d569771a8ae2be24c34f5369383b4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListBaseFragment.kt
@@ -41,9 +41,9 @@ import de.kuschku.libquassel.util.Optional
 import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.libquassel.util.flag.minus
 import de.kuschku.libquassel.util.flag.plus
+import de.kuschku.libquassel.util.helper.combineLatest
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.Defaults
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.ui.settings.fragment.Changeable
 import de.kuschku.quasseldroid.util.ui.settings.fragment.Savable
@@ -138,7 +138,7 @@ abstract class ChatListBaseFragment(private val initDefault: Boolean) :
     })
 
     if (initDefault) {
-      modelHelper.session
+      modelHelper.connectedSession
         .filter(Optional<ISession>::isPresent)
         .map(Optional<ISession>::get)
         .firstElement()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListCreateFragment.kt
index 57a87610cd42586bad3a8d0763298edbe9e281fd..431099cbe0d592a0aabf63d923086312b9d2df43 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListCreateFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListCreateFragment.kt
@@ -19,7 +19,7 @@
 
 package de.kuschku.quasseldroid.ui.coresettings.chatlist
 
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 
 class ChatListCreateFragment : ChatListBaseFragment(true) {
   override fun onSave() = chatlist?.let { (_, data) ->
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListEditFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListEditFragment.kt
index b94bc5eac0f998634c3cec7a7268d914d864e154..f3d568f538319b1db82c0d60c2df7a9490e84678 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListEditFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListEditFragment.kt
@@ -19,7 +19,7 @@
 
 package de.kuschku.quasseldroid.ui.coresettings.chatlist
 
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.util.ui.settings.fragment.Deletable
 
 class ChatListEditFragment : ChatListBaseFragment(false), Deletable {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
index b0bd1f62922342643f4929660c2b4c5829c64ec6..c0d6b152eb63769d292b1729ff2e3a516f8afbb3 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityBaseFragment.kt
@@ -127,7 +127,7 @@ abstract class IdentityBaseFragment(private val initDefault: Boolean) :
     }
 
     if (initDefault) {
-      modelHelper.session
+      modelHelper.connectedSession
         .filter(Optional<ISession>::isPresent)
         .map(Optional<ISession>::get)
         .firstElement()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityCreateFragment.kt
index 55679aae32c666c6611d8ced7ed791658f08c2e5..41c46ca485fa79120389a2fc9c6722116adf19bd 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityCreateFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityCreateFragment.kt
@@ -19,10 +19,10 @@
 
 package de.kuschku.quasseldroid.ui.coresettings.identity
 
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 
 class IdentityCreateFragment : IdentityBaseFragment(true) {
-  override fun onSave() = modelHelper.session.value?.orNull()?.let { session ->
+  override fun onSave() = modelHelper.connectedSession.value?.orNull()?.let { session ->
     identity?.let { (_, data) ->
       applyChanges(data)
       session.rpcHandler.createIdentity(data, mapOf())
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityEditFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityEditFragment.kt
index 4523eb3b46baa4ec86ee622c59eed6cb3a2f3157..48e9e8a2543c9f85474ab1ca6fc9854816e87ee7 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityEditFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityEditFragment.kt
@@ -19,7 +19,7 @@
 
 package de.kuschku.quasseldroid.ui.coresettings.identity
 
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.util.ui.settings.fragment.Deletable
 
 class IdentityEditFragment : IdentityBaseFragment(false), Deletable {
@@ -32,7 +32,7 @@ class IdentityEditFragment : IdentityBaseFragment(false), Deletable {
   override fun onDelete() {
     identity?.let { (it, _) ->
       it?.let {
-        modelHelper.session.value?.orNull()?.rpcHandler?.removeIdentity(it.id())
+        modelHelper.connectedSession.value?.orNull()?.rpcHandler?.removeIdentity(it.id())
       }
     }
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
index 921fc53971e1ff3d16247a2418f619c49432324a..8148805de8cc49da1005e09c2b1e27a879aa25c6 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkBaseFragment.kt
@@ -43,12 +43,12 @@ import de.kuschku.libquassel.quassel.syncables.Network
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.Optional
-import de.kuschku.libquassel.util.helpers.nullIf
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.nullIf
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.Defaults
 import de.kuschku.quasseldroid.ui.coresettings.networkserver.NetworkServerActivity
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.setDependent
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.helper.visibleIf
@@ -188,7 +188,7 @@ abstract class NetworkBaseFragment(private val initDefault: Boolean) :
     })
 
     if (initDefault) {
-      modelHelper.session
+      modelHelper.connectedSession
         .filter(Optional<ISession>::isPresent)
         .map(Optional<ISession>::get)
         .firstElement()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt
index 30a627384d446dc391fdea35fe85d61c0a262495..56354293db639106e976684c873f801e55c66542 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt
@@ -19,11 +19,11 @@
 
 package de.kuschku.quasseldroid.ui.coresettings.network
 
-import de.kuschku.libquassel.session.Backend
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
+import de.kuschku.quasseldroid.Backend
 
 class NetworkCreateFragment : NetworkBaseFragment(true) {
-  override fun onSave() = modelHelper.session.value?.orNull()?.let { session ->
+  override fun onSave() = modelHelper.connectedSession.value?.orNull()?.let { session ->
     network?.let { (_, data) ->
       applyChanges(data)
       modelHelper.backend.value?.ifPresent(Backend::requestConnectNewNetwork)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkEditFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkEditFragment.kt
index 1c76a2a7d5559ed323cc902d6d3897ca74343339..4d7900e4f004ab928311b3f9786a3382e413a9ba 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkEditFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkEditFragment.kt
@@ -19,7 +19,7 @@
 
 package de.kuschku.quasseldroid.ui.coresettings.network
 
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.util.ui.settings.fragment.Deletable
 
 class NetworkEditFragment : NetworkBaseFragment(false), Deletable {
@@ -32,7 +32,7 @@ class NetworkEditFragment : NetworkBaseFragment(false), Deletable {
   override fun onDelete() {
     network?.let { (it, _) ->
       it?.let {
-        modelHelper.session.value?.orNull()?.rpcHandler?.removeNetwork(it.networkId())
+        modelHelper.connectedSession.value?.orNull()?.rpcHandler?.removeNetwork(it.networkId())
       }
     }
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/passwordchange/PasswordChangeFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/passwordchange/PasswordChangeFragment.kt
index c77211353d58e19ba0eac2aa574aeffebaf78599..04ddb0c964ad1210370441bfe1ad5809a0046d5a 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/passwordchange/PasswordChangeFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/passwordchange/PasswordChangeFragment.kt
@@ -34,9 +34,9 @@ import com.google.android.material.textfield.TextInputLayout
 import de.kuschku.libquassel.quassel.syncables.RpcHandler
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.Optional
-import de.kuschku.libquassel.util.helpers.mapMapNullable
-import de.kuschku.libquassel.util.helpers.mapSwitchMap
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.mapMapNullable
+import de.kuschku.libquassel.util.helper.mapSwitchMap
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.persistence.db.AccountDatabase
 import de.kuschku.quasseldroid.persistence.models.Account
@@ -92,7 +92,7 @@ class PasswordChangeFragment : ServiceBoundFragment() {
 
     user.setText(account?.user)
 
-    modelHelper.session
+    modelHelper.connectedSession
       .mapMapNullable(ISession::rpcHandler)
       .mapSwitchMap(RpcHandler::passwordChanged)
       .filter(Optional<Boolean>::isPresent)
@@ -144,7 +144,7 @@ class PasswordChangeFragment : ServiceBoundFragment() {
 
       waiting = account?.copy(pass = pass)
 
-      modelHelper.session.value?.orNull()?.rpcHandler?.changePassword(
+      modelHelper.connectedSession.value?.orNull()?.rpcHandler?.changePassword(
         0L,
         user.text.toString(),
         oldPassword.text.toString(),
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/channel/ChannelInfoFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/channel/ChannelInfoFragment.kt
index 49b933ff34d6fbb9ed2b423a64e308de8fc0063f..9706bbee6eb1490b8eb818d919e63b039d8d7e4e 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/channel/ChannelInfoFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/channel/ChannelInfoFragment.kt
@@ -34,7 +34,8 @@ import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.quassel.syncables.IrcChannel
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.ui.chat.topic.TopicActivity
@@ -90,7 +91,8 @@ class ChannelInfoFragment : ServiceBoundFragment() {
 
     var currentBufferInfo: BufferInfo?
 
-    combineLatest(modelHelper.session, modelHelper.networks).map { (sessionOptional, networks) ->
+    combineLatest(modelHelper.connectedSession,
+                  modelHelper.networks).map { (sessionOptional, networks) ->
       if (openBuffer == true) {
         val session = sessionOptional?.orNull()
         val bufferSyncer = session?.bufferSyncer
@@ -127,7 +129,7 @@ class ChannelInfoFragment : ServiceBoundFragment() {
       }
 
       actionPart.setOnClickListener {
-        modelHelper.session.value?.orNull()?.let { session ->
+        modelHelper.connectedSession.value?.orNull()?.let { session ->
           session.bufferSyncer.find(
             networkId = channel.network().networkId(),
             type = Buffer_Type.of(Buffer_Type.StatusBuffer)
@@ -139,7 +141,7 @@ class ChannelInfoFragment : ServiceBoundFragment() {
       }
 
       actionWho.setOnClickListener {
-        modelHelper.session.value?.orNull()?.let { session ->
+        modelHelper.connectedSession.value?.orNull()?.let { session ->
           session.bufferSyncer.find(
             networkId = channel.network().networkId(),
             type = Buffer_Type.of(Buffer_Type.StatusBuffer)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/channellist/ChannelListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/channellist/ChannelListFragment.kt
index e5fbcc0c3055d6558d7ef46227d0351f4c4bccc4..0b02d561ab680a9588f208240d3b5bd32fadd454 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/channellist/ChannelListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/channellist/ChannelListFragment.kt
@@ -34,10 +34,10 @@ import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.protocol.QStringList
 import de.kuschku.libquassel.quassel.syncables.IrcListHelper
 import de.kuschku.libquassel.util.Optional
-import de.kuschku.libquassel.util.helpers.mapSwitchMap
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.mapSwitchMap
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.R
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.retint
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.ui.settings.fragment.ServiceBoundSettingsFragment
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/core/CoreInfoFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/core/CoreInfoFragment.kt
index 2ac930c12c2234c4a50f6314e1e51713f0930abb..d939e93da4ac40d7d33bf6485dfe19229d8a3adb 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/core/CoreInfoFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/core/CoreInfoFragment.kt
@@ -35,7 +35,8 @@ import butterknife.ButterKnife
 import de.kuschku.libquassel.quassel.QuasselFeatures
 import de.kuschku.libquassel.ssl.X509Helper
 import de.kuschku.libquassel.ssl.commonName
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.ui.info.certificate.CertificateInfoActivity
 import de.kuschku.quasseldroid.util.helper.*
@@ -205,7 +206,7 @@ class CoreInfoFragment : ServiceBoundFragment() {
     clients.layoutManager = LinearLayoutManager(requireContext())
     val adapter = ClientAdapter()
     adapter.setDisconnectListener {
-      val sessionOptional = modelHelper.session.value
+      val sessionOptional = modelHelper.connectedSession.value
       val session = sessionOptional?.orNull()
       val rpcHandler = session?.rpcHandler
       rpcHandler?.requestKickClient(it)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt
index 6bb05c0a9632233d4a4aa68d2643aba3c6cc3abb..91de4fbbdc8257d8270910f4d6e12805d091d1ec 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt
@@ -47,8 +47,10 @@ import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
 import de.kuschku.libquassel.quassel.syncables.IrcChannel
 import de.kuschku.libquassel.quassel.syncables.IrcUser
 import de.kuschku.libquassel.util.Optional
-import de.kuschku.libquassel.util.helpers.nullIf
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.invoke
+import de.kuschku.libquassel.util.helper.nullIf
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.libquassel.util.irc.HostmaskHelper
 import de.kuschku.libquassel.util.irc.IrcCaseMappers
 import de.kuschku.quasseldroid.R
@@ -179,7 +181,7 @@ class UserInfoFragment : ServiceBoundFragment() {
       getColor(0, 0)
     }
 
-    combineLatest(modelHelper.session,
+    combineLatest(modelHelper.connectedSession,
                   modelHelper.networks).switchMap { (sessionOptional, networks) ->
       fun processUser(user: IrcUser, bufferSyncer: BufferSyncer? = null, info: BufferInfo? = null,
                       ignoreItems: List<IgnoreListManager.IgnoreListItem>? = null): Observable<Optional<IrcUserInfo>> {
@@ -352,7 +354,7 @@ class UserInfoFragment : ServiceBoundFragment() {
         actionWhois.visibleIf(user.knownToCore)
 
         actionQuery.setOnClickListener { view ->
-          modelHelper.session.value?.orNull()?.let { session ->
+          modelHelper.connectedSession.value?.orNull()?.let { session ->
             val info = session.bufferSyncer.find(
               bufferName = user.nick,
               networkId = user.networkId,
@@ -433,7 +435,7 @@ class UserInfoFragment : ServiceBoundFragment() {
         }
 
         actionWhois.setOnClickListener { view ->
-          modelHelper.session {
+          modelHelper.connectedSession {
             it.orNull()?.let { session ->
               session.bufferSyncer.find(
                 networkId = user.networkId,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ServiceBoundSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ServiceBoundSetupActivity.kt
index fd8005c1a910fef206bc68ee748879030334723f..73f206f549cf9d437c39eb725bfe5b39f6046903 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ServiceBoundSetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ServiceBoundSetupActivity.kt
@@ -34,9 +34,9 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import com.google.android.material.floatingactionbutton.FloatingActionButton
 import dagger.android.support.DaggerAppCompatActivity
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.util.Optional
-import de.kuschku.libquassel.util.helpers.nullIf
+import de.kuschku.libquassel.util.helper.nullIf
+import de.kuschku.quasseldroid.Backend
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AppearanceSettings
@@ -82,13 +82,13 @@ abstract class ServiceBoundSetupActivity :
   protected open val initData: Bundle = Bundle()
 
   protected fun runInBackground(f: () -> Unit) {
-    connection.backend.value.ifPresent {
+    connection.backend.value?.ifPresent {
       it.sessionManager()?.handlerService?.backend(f)
     }
   }
 
   protected fun runInBackgroundDelayed(delayMillis: Long, f: () -> Unit) {
-    connection.backend.value.ifPresent {
+    connection.backend.value?.ifPresent {
       it.sessionManager()?.handlerService?.backendDelayed(delayMillis, f)
     }
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ServiceBoundSlideFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ServiceBoundSlideFragment.kt
index 6d065af8e887821d99c6e7deea6ecdb9c347ea5a..f4058e54a0d6e36a4691aa450c57991111d027d4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ServiceBoundSlideFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ServiceBoundSlideFragment.kt
@@ -21,8 +21,8 @@ package de.kuschku.quasseldroid.ui.setup
 
 import android.content.Context
 import android.os.Bundle
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.util.Optional
+import de.kuschku.quasseldroid.Backend
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.util.service.BackendServiceConnection
 import io.reactivex.subjects.BehaviorSubject
@@ -33,13 +33,13 @@ abstract class ServiceBoundSlideFragment : SlideFragment() {
     get() = connection.backend
 
   protected fun runInBackground(f: () -> Unit) {
-    connection.backend.value.ifPresent {
+    connection.backend.value?.ifPresent {
       it.sessionManager()?.handlerService?.backend(f)
     }
   }
 
   protected fun runInBackgroundDelayed(delayMillis: Long, f: () -> Unit) {
-    connection.backend.value.ifPresent {
+    connection.backend.value?.ifPresent {
       it.sessionManager()?.handlerService?.backendDelayed(delayMillis, f)
     }
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/SetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/SetupActivity.kt
index a24d8dee2abf78af7088379bc262bc9ad747b072..be71c78d28fa5d5afe895b6ccdb0f9bea438b2d6 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/SetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/SetupActivity.kt
@@ -33,7 +33,7 @@ import butterknife.BindView
 import butterknife.ButterKnife
 import com.google.android.material.floatingactionbutton.FloatingActionButton
 import dagger.android.support.DaggerAppCompatActivity
-import de.kuschku.libquassel.util.helpers.nullIf
+import de.kuschku.libquassel.util.helper.nullIf
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.ui.clientsettings.about.AboutActivity
 import de.kuschku.quasseldroid.ui.clientsettings.client.ClientSettingsActivity
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt
index b3a942f9ee47407dfb568aeaa287428a466500a4..b8520d141b035526a968447e1ed20ba343237b3a 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt
@@ -28,7 +28,7 @@ import de.kuschku.libquassel.protocol.coresetup.CoreSetupBackend
 import de.kuschku.libquassel.protocol.coresetup.CoreSetupData
 import de.kuschku.libquassel.protocol.message.HandshakeMessage
 import de.kuschku.libquassel.quassel.ExtendedFeature
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.persistence.models.Account
 import de.kuschku.quasseldroid.ui.setup.ServiceBoundSetupActivity
 import de.kuschku.quasseldroid.viewmodel.helper.EditorViewModelHelper
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupActivity.kt
index e1ae92985394b757b2ec0480c615ac9295a0cfcc..864090fe2596218e777c259d52488944a85d3f21 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupActivity.kt
@@ -27,7 +27,7 @@ import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.protocol.IdentityId
 import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.ui.setup.ServiceBoundSetupActivity
 import de.kuschku.quasseldroid.viewmodel.helper.EditorViewModelHelper
 import javax.inject.Inject
@@ -51,7 +51,7 @@ class NetworkSetupActivity : ServiceBoundSetupActivity() {
     val identity = IdentityId(data.getInt("identity", -1))
     if (networkId.isValidId() || (network != null && identity.isValidId())) {
       modelHelper.backend?.value?.ifPresent { backend ->
-        val session = modelHelper.session.value?.orNull()
+        val session = modelHelper.connectedSession.value?.orNull()
         session?.apply {
           rpcHandler.apply {
             when {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupNetworkSlide.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupNetworkSlide.kt
index 19a2297701901feb81e916b1ef4d0fc82dda56fa..4d59cdd91b3f5fd44f09d4d6a58abd45680616c9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupNetworkSlide.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupNetworkSlide.kt
@@ -39,6 +39,7 @@ import de.kuschku.libquassel.quassel.syncables.Network
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.PortDefaults.PORT_PLAINTEXT
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.PortDefaults.PORT_SSL
+import de.kuschku.libquassel.util.helper.combineLatest
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.DefaultNetworkServer
 import de.kuschku.quasseldroid.ui.coresettings.chatlist.NetworkAdapter
@@ -46,7 +47,6 @@ import de.kuschku.quasseldroid.ui.coresettings.network.IdentityAdapter
 import de.kuschku.quasseldroid.ui.setup.ServiceBoundSlideFragment
 import de.kuschku.quasseldroid.util.Patterns
 import de.kuschku.quasseldroid.util.TextValidator
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.ui.AnimationHelper
 import de.kuschku.quasseldroid.viewmodel.helper.EditorViewModelHelper
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupActivity.kt
index 292f05833301e243a0d8e61157aa7de0f055ad65..e063508add84b059dce24cf9d100c59ddfe90a23 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupActivity.kt
@@ -27,7 +27,7 @@ import androidx.lifecycle.Observer
 import de.kuschku.libquassel.protocol.IdentityId
 import de.kuschku.libquassel.quassel.syncables.Identity
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
-import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.helper.value
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.DefaultNetwork
 import de.kuschku.quasseldroid.defaults.Defaults
@@ -51,7 +51,7 @@ class UserSetupActivity : ServiceBoundSetupActivity() {
     val network = data.getSerializable("network") as? DefaultNetwork
     if (network != null) {
       modelHelper.backend?.value?.ifPresent { backend ->
-        modelHelper.session.value?.orNull()?.rpcHandler?.apply {
+        modelHelper.connectedSession.value?.orNull()?.rpcHandler?.apply {
           createIdentity(Defaults.identity(this@UserSetupActivity).apply {
             setIdentityName(this@UserSetupActivity.getString(R.string.default_identity_identity_name))
             setNicks(listOf(data.getString("nick")))
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupNetworkSlide.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupNetworkSlide.kt
index 8e6795c5a6c29de7b0ad1b0bb0580be67369d363..d88581f54e1b9a16a524aaa29554dd7541be9f18 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupNetworkSlide.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupNetworkSlide.kt
@@ -33,7 +33,7 @@ import butterknife.ButterKnife
 import com.google.android.material.textfield.TextInputLayout
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.PortDefaults.PORT_PLAINTEXT
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.PortDefaults.PORT_SSL
-import de.kuschku.libquassel.util.helpers.nullIf
+import de.kuschku.libquassel.util.helper.nullIf
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.defaults.DefaultNetwork
 import de.kuschku.quasseldroid.defaults.DefaultNetworkServer
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/compatibility/AndroidLoggingHandler.kt b/app/src/main/java/de/kuschku/quasseldroid/util/compatibility/AndroidLoggingHandler.kt
index 170644894329134547df0070b6763b932d2f7da1..2ced1011a3c8fbd99e4423aa5ba4cb2bb945ee64 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/compatibility/AndroidLoggingHandler.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/compatibility/AndroidLoggingHandler.kt
@@ -24,11 +24,11 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler
 import de.kuschku.quasseldroid.BuildConfig
 
 object AndroidLoggingHandler : LoggingHandler() {
-  override fun isLoggable(logLevel: LogLevel, tag: String): Boolean {
+  override fun _isLoggable(logLevel: LogLevel, tag: String): Boolean {
     return BuildConfig.DEBUG || Log.isLoggable(tag, priority(logLevel))
   }
 
-  override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
+  override fun _log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
     val priority = priority(
       logLevel
     )
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/helper/IntRangeHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/helper/IntRangeHelper.kt
index ee13b1140f4fe702b3402e4b16e6f606397bf917..58ef4abb62302f05f5bc7005fc57b8a0733d10a4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/helper/IntRangeHelper.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/helper/IntRangeHelper.kt
@@ -19,7 +19,7 @@
 
 package de.kuschku.quasseldroid.util.helper
 
-import de.kuschku.libquassel.util.helpers.clampOf
+import de.kuschku.libquassel.util.helper.clampOf
 
 infix fun IntRange.without(other: IntRange): Iterable<IntRange> {
   val otherStart = clampOf(minOf(other.start, other.last + 1), this.start, this.last + 1)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/service/BackendServiceConnection.kt b/app/src/main/java/de/kuschku/quasseldroid/util/service/BackendServiceConnection.kt
index 2d375b908b386912169bf88880dbffa392c9f653..89dfb55497c177fb4f2e0deb0f64769933d3d4d9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/service/BackendServiceConnection.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/service/BackendServiceConnection.kt
@@ -26,8 +26,8 @@ import android.content.ServiceConnection
 import android.os.IBinder
 import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.LifecycleOwner
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.util.Optional
+import de.kuschku.quasseldroid.Backend
 import de.kuschku.quasseldroid.service.QuasselBinder
 import de.kuschku.quasseldroid.service.QuasselService
 import io.reactivex.subjects.BehaviorSubject
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt
index ed62a7d1a4dc7595283089dedf818b58aeeb6f9a..38749538fa786c00cea0c7f9055dbd18f1e3191d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt
@@ -29,8 +29,8 @@ import android.view.WindowManager
 import android.widget.Toast
 import androidx.annotation.ColorRes
 import androidx.annotation.DrawableRes
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.util.Optional
+import de.kuschku.quasseldroid.Backend
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.ConnectionSettings
@@ -58,13 +58,13 @@ abstract class ServiceBoundActivity :
   private var nightMode: Int? = null
 
   protected fun runInBackground(f: () -> Unit) {
-    connection.backend.value.ifPresent {
+    connection.backend.value?.ifPresent {
       it.sessionManager()?.handlerService?.backend(f)
     }
   }
 
   protected fun runInBackgroundDelayed(delayMillis: Long, f: () -> Unit) {
-    connection.backend.value.ifPresent {
+    connection.backend.value?.ifPresent {
       it.sessionManager()?.handlerService?.backendDelayed(delayMillis, f)
     }
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundFragment.kt
index 75cba1a039acdabd83d975cea960288da5c22f3b..f7f493faf17ccbde1e53a4a8681ee13c6a220190 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundFragment.kt
@@ -22,8 +22,8 @@ package de.kuschku.quasseldroid.util.service
 import android.content.Context
 import android.os.Bundle
 import dagger.android.support.DaggerFragment
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.util.Optional
+import de.kuschku.quasseldroid.Backend
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.viewmodel.QuasselViewModel
 import io.reactivex.subjects.BehaviorSubject
@@ -38,13 +38,13 @@ abstract class ServiceBoundFragment : DaggerFragment() {
     get() = connection.backend
 
   protected fun runInBackground(f: () -> Unit) {
-    connection.backend.value.ifPresent {
+    connection.backend.value?.ifPresent {
       it.sessionManager()?.handlerService?.backend(f)
     }
   }
 
   protected fun runInBackgroundDelayed(delayMillis: Long, f: () -> Unit) {
-    connection.backend.value.ifPresent {
+    connection.backend.value?.ifPresent {
       it.sessionManager()?.handlerService?.backendDelayed(delayMillis, f)
     }
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/ThemedActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/ThemedActivity.kt
index d688cc0d5bfb6f99b8dba758452b210f3ce3326d..66f7255a3c75e977b835c3d6b3ee7b7cd7ddd24a 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/ThemedActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/ThemedActivity.kt
@@ -29,7 +29,7 @@ import dagger.android.AndroidInjector
 import dagger.android.DispatchingAndroidInjector
 import dagger.android.HasFragmentInjector
 import dagger.android.support.HasSupportFragmentInjector
-import de.kuschku.libquassel.util.helpers.nullIf
+import de.kuschku.libquassel.util.helper.nullIf
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import javax.inject.Inject
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt b/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
index 4f1ffca9714cb773f6ba474ecdac68e882d9c785..11147935ae1fc51d8e21d14b634bae8676ca0727 100644
--- a/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/connection/CoreConnection.kt
@@ -39,8 +39,8 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.DEBUG
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.WARN
 import de.kuschku.libquassel.util.compatibility.reference.JavaHandlerService
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.libquassel.util.helpers.hexDump
-import de.kuschku.libquassel.util.helpers.write
+import de.kuschku.libquassel.util.helper.hexDump
+import de.kuschku.libquassel.util.helper.write
 import de.kuschku.libquassel.util.nio.ChainedByteBuffer
 import de.kuschku.libquassel.util.nio.WrappedChannel
 import io.reactivex.subjects.BehaviorSubject
diff --git a/lib/src/main/java/de/kuschku/libquassel/connection/MessageRunnable.kt b/lib/src/main/java/de/kuschku/libquassel/connection/MessageRunnable.kt
index 2236b83ea2eab124d549d050b4f1abc5df73c112..ff3e5e6d7e47bf8f32d9c2fa039cbc360d5fd016 100644
--- a/lib/src/main/java/de/kuschku/libquassel/connection/MessageRunnable.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/connection/MessageRunnable.kt
@@ -23,7 +23,7 @@ import de.kuschku.libquassel.protocol.primitive.serializer.Serializer
 import de.kuschku.libquassel.quassel.QuasselFeatures
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.WARN
-import de.kuschku.libquassel.util.helpers.write
+import de.kuschku.libquassel.util.helper.write
 import de.kuschku.libquassel.util.nio.ChainedByteBuffer
 import de.kuschku.libquassel.util.nio.WrappedChannel
 import java.nio.ByteBuffer
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/QTypes.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/QTypes.kt
index 6dc8b55856af12538ba38c41bda8265ec880e578..4b1c6a2d900a7f93b59f12226d02e91829bf34c6 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/QTypes.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/QTypes.kt
@@ -27,7 +27,7 @@ import de.kuschku.libquassel.quassel.ProtocolFeature
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.util.flag.Flags
 import de.kuschku.libquassel.util.flag.ShortFlags
-import de.kuschku.libquassel.util.helpers.deserializeString
+import de.kuschku.libquassel.util.helper.deserializeString
 import java.nio.ByteBuffer
 
 typealias QStringList = List<String?>
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/coresetup/CoreSetupBackend.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/coresetup/CoreSetupBackend.kt
index bd0d861b9ac37cb40e5ac57847eb26f6d5bbab4b..fc958810e1a5bf0f6f41c457a915e7318fbfec9b 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/coresetup/CoreSetupBackend.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/coresetup/CoreSetupBackend.kt
@@ -20,7 +20,7 @@
 package de.kuschku.libquassel.protocol.coresetup
 
 import de.kuschku.libquassel.protocol.*
-import de.kuschku.libquassel.util.helpers.getOr
+import de.kuschku.libquassel.util.helper.getOr
 import java.io.Serializable
 
 data class CoreSetupBackend(
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/message/InitDataSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/message/InitDataSerializer.kt
index 704bc471ef115bd87769435b265dcd9139139dec..73e9f86c31d6e953037fa7d695f0f01ce3b4cca1 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/message/InitDataSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/message/InitDataSerializer.kt
@@ -21,8 +21,8 @@ package de.kuschku.libquassel.protocol.message
 
 import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
-import de.kuschku.libquassel.util.helpers.deserializeString
-import de.kuschku.libquassel.util.helpers.serializeString
+import de.kuschku.libquassel.util.helper.deserializeString
+import de.kuschku.libquassel.util.helper.serializeString
 import java.nio.ByteBuffer
 
 object InitDataSerializer : SignalProxyMessageSerializer<SignalProxyMessage.InitData> {
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/message/InitRequestSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/message/InitRequestSerializer.kt
index c5bb53f922fb91d8df62b14c7f96149587c6d5f5..2ebef5f71dbcc520b5ebcc4689621e8a3d3622e6 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/message/InitRequestSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/message/InitRequestSerializer.kt
@@ -24,8 +24,8 @@ import de.kuschku.libquassel.protocol.QVariantList
 import de.kuschku.libquassel.protocol.Type
 import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
 import de.kuschku.libquassel.protocol.value
-import de.kuschku.libquassel.util.helpers.deserializeString
-import de.kuschku.libquassel.util.helpers.serializeString
+import de.kuschku.libquassel.util.helper.deserializeString
+import de.kuschku.libquassel.util.helper.serializeString
 import java.nio.ByteBuffer
 
 object InitRequestSerializer : SignalProxyMessageSerializer<SignalProxyMessage.InitRequest> {
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/message/RpcCallSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/message/RpcCallSerializer.kt
index a5da9505b3602656b7d17fcad329df4bf0b6b1bd..25fdf96dd0e50a9494d64109e656ea36b0e44aea 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/message/RpcCallSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/message/RpcCallSerializer.kt
@@ -24,8 +24,8 @@ import de.kuschku.libquassel.protocol.QVariantList
 import de.kuschku.libquassel.protocol.Type
 import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
 import de.kuschku.libquassel.protocol.value
-import de.kuschku.libquassel.util.helpers.deserializeString
-import de.kuschku.libquassel.util.helpers.serializeString
+import de.kuschku.libquassel.util.helper.deserializeString
+import de.kuschku.libquassel.util.helper.serializeString
 import java.nio.ByteBuffer
 
 object RpcCallSerializer : SignalProxyMessageSerializer<SignalProxyMessage.RpcCall> {
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/message/SyncMessageSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/message/SyncMessageSerializer.kt
index 203b8647f4c6181f74019296429bdf42dead148d..98bf74f7eba59ea5aabb92550635d40547a3de5e 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/message/SyncMessageSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/message/SyncMessageSerializer.kt
@@ -24,8 +24,8 @@ import de.kuschku.libquassel.protocol.QVariantList
 import de.kuschku.libquassel.protocol.Type
 import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
 import de.kuschku.libquassel.protocol.value
-import de.kuschku.libquassel.util.helpers.deserializeString
-import de.kuschku.libquassel.util.helpers.serializeString
+import de.kuschku.libquassel.util.helper.deserializeString
+import de.kuschku.libquassel.util.helper.serializeString
 import java.nio.ByteBuffer
 
 object SyncMessageSerializer : SignalProxyMessageSerializer<SignalProxyMessage.SyncMessage> {
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
index 3c61e8d6bfefd63ad1d8d209533876058b42d2c4..7dbdd0cfe979a9d759e51f9c16d53a33f0249639 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
@@ -21,7 +21,7 @@
 package de.kuschku.libquassel.protocol.primitive.serializer
 
 import de.kuschku.libquassel.quassel.QuasselFeatures
-import de.kuschku.libquassel.util.helpers.hexDump
+import de.kuschku.libquassel.util.helper.hexDump
 import de.kuschku.libquassel.util.nio.ChainedByteBuffer
 import java.nio.ByteBuffer
 import java.nio.CharBuffer
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 22ebb65efb8ce8ab763fc72fb6316e27b2c5b2af..6574f18e2a246988767b4b622b2573d36e4ddf8a 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
@@ -25,7 +25,7 @@ import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.quassel.syncables.interfaces.IBufferViewConfig
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.libquassel.util.helpers.clampOf
+import de.kuschku.libquassel.util.helper.clampOf
 import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
index 7b9d44b0191df80ffd57afa30cb2c71d0eb16edd..fcdff341be0473e38f4e4925338e6910031aee8c 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
@@ -27,7 +27,7 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.ERROR
-import de.kuschku.libquassel.util.helpers.getOr
+import de.kuschku.libquassel.util.helper.getOr
 import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 import java.nio.charset.Charset
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
index 41a5a1d01568b6bdfba7009fd6a3b61d82bde2e8..8fd5e42e6b68bb54799e11b6a76657cf9c0a8e92 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
@@ -25,8 +25,8 @@ import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork.*
 import de.kuschku.libquassel.session.SignalProxy
-import de.kuschku.libquassel.util.helpers.getOr
-import de.kuschku.libquassel.util.helpers.serializeString
+import de.kuschku.libquassel.util.helper.getOr
+import de.kuschku.libquassel.util.helper.serializeString
 import de.kuschku.libquassel.util.irc.HostmaskHelper
 import de.kuschku.libquassel.util.irc.IrcCaseMappers
 import io.reactivex.Observable
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
index 524a0f2631158313f9b4e1c4bbeb248419ec194f..6a284a5b9393e97ae39aa72f2463c9bf41919981 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt
@@ -28,7 +28,7 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.IRpcHandler
 import de.kuschku.libquassel.session.BacklogStorage
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.session.NotificationManager
-import de.kuschku.libquassel.util.helpers.deserializeString
+import de.kuschku.libquassel.util.helper.deserializeString
 import de.kuschku.libquassel.util.rxjava.ReusableUnicastSubject
 import java.nio.ByteBuffer
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
index ead6bc2cd6e9883751409d88455dc087bf704b17..b6e93937938e15536c1e338ca425fc58837974fe 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
@@ -25,7 +25,7 @@ import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
 import de.kuschku.libquassel.util.flag.Flag
 import de.kuschku.libquassel.util.flag.Flags
-import de.kuschku.libquassel.util.helpers.serializeString
+import de.kuschku.libquassel.util.helper.serializeString
 import java.io.Serializable
 import java.nio.ByteBuffer
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Error.kt b/lib/src/main/java/de/kuschku/libquassel/session/Error.kt
index 0461ee6d3aac66e3ee85b1f304a4f37f4feef621..3e791862b8edb15557afd60203f5ff868de35345 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Error.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Error.kt
@@ -23,6 +23,7 @@ import de.kuschku.libquassel.connection.QuasselSecurityException
 import de.kuschku.libquassel.protocol.message.HandshakeMessage
 
 sealed class Error {
-  data class HandshakeError(val message: HandshakeMessage) : Error()
+  data class ConnectionError(val throwable: Throwable) : Error()
   data class SslError(val exception: QuasselSecurityException) : Error()
+  data class HandshakeError(val message: HandshakeMessage) : Error()
 }
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 84fd10247766cd4630c4c41b5682d59c8153a076..82b1321e37256c98901dd927c7256f222f1f04c0 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt
@@ -35,9 +35,11 @@ import java.io.Closeable
 import javax.net.ssl.SSLSession
 
 interface ISession : Closeable {
-  val state: Observable<ConnectionState>
   val features: Features
   val sslSession: Observable<Optional<SSLSession>>
+  val lag: BehaviorSubject<Long>
+
+  val proxy: SignalProxy
 
   val aliasManager: AliasManager
   val backlogManager: BacklogManager
@@ -56,16 +58,9 @@ interface ISession : Closeable {
   fun liveNetworkAdded(): Observable<NetworkId>
   val networkConfig: NetworkConfig
   val rpcHandler: RpcHandler
-  val initStatus: Observable<Pair<Int, Int>>
-
   fun network(id: NetworkId): Network?
   fun identity(id: IdentityId): Identity?
 
-  val proxy: SignalProxy
-  val error: Observable<Error>
-  val connectionError: Observable<Throwable>
-  val lag: BehaviorSubject<Long>
-
   fun login(user: String, pass: String)
   fun setupCore(setupData: HandshakeMessage.CoreSetupData) {
     proxy.dispatch(setupData)
@@ -77,16 +72,23 @@ interface ISession : Closeable {
   fun addIdentity(initData: QVariantMap)
   fun removeIdentity(identityId: IdentityId)
 
+  val progress: ProgressData
+
+  data class ProgressData(
+    val state: Observable<ConnectionState>,
+    val progress: Observable<Pair<Int, Int>>,
+    val error: Observable<Error>
+  )
+
   companion object {
     val NULL = object : ISession {
-      override val proxy: SignalProxy = SignalProxy.NULL
-      override val error = Observable.empty<Error>()
-      override val connectionError = Observable.empty<Throwable>()
-      override val state = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED)
       override val features: Features = Features(
         QuasselFeatures.empty(),
         QuasselFeatures.empty())
       override val sslSession: Observable<Optional<SSLSession>> = Observable.empty()
+      override val lag = BehaviorSubject.createDefault(0L)
+
+      override val proxy: SignalProxy = SignalProxy.NULL
 
       override val rpcHandler = RpcHandler(this)
       override val aliasManager = AliasManager(proxy)
@@ -105,8 +107,6 @@ interface ISession : Closeable {
       override fun liveNetworks() = Observable.empty<Map<NetworkId, Network>>()
       override fun liveNetworkAdded(): Observable<NetworkId> = PublishSubject.create()
       override val networkConfig = NetworkConfig(proxy)
-      override val initStatus: Observable<Pair<Int, Int>> = Observable.just(0 to 0)
-      override val lag = BehaviorSubject.createDefault(0L)
 
       override fun network(id: NetworkId): Network? = null
       override fun identity(id: IdentityId): Identity? = null
@@ -118,6 +118,13 @@ interface ISession : Closeable {
       override fun removeNetwork(networkId: NetworkId) = Unit
       override fun addIdentity(initData: QVariantMap) = Unit
       override fun removeIdentity(identityId: IdentityId) = Unit
+
+      override val progress = ProgressData(
+        state = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED),
+        progress = BehaviorSubject.createDefault(Pair(0, 0)),
+        error = Observable.empty()
+      )
+
       override fun close() = Unit
     }
   }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt b/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
index 79630f8423b1a8f87ad2bb363f630ed6cb4bb59b..914d829a7256a09744e768c66f996b36635c5bdc 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
@@ -25,7 +25,7 @@ import de.kuschku.libquassel.protocol.Type
 import de.kuschku.libquassel.protocol.message.SignalProxyMessage
 import de.kuschku.libquassel.quassel.exceptions.ObjectNotFoundException
 import de.kuschku.libquassel.quassel.syncables.interfaces.ISyncableObject
-import de.kuschku.libquassel.util.helpers.removeIfEqual
+import de.kuschku.libquassel.util.helper.removeIfEqual
 
 class ObjectStorage(private var proxy: SignalProxy) {
   fun deinit() {
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 346f33d4df086387aa66c3d661cca348aef067ba..91eaf398bc434b7b1cc3058feafd3d618b87906d 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
@@ -71,12 +71,15 @@ class Session(
     trustManager,
     hostnameVerifier
   )
-  override val state = coreConnection.state
 
-  private val _error = ReusableUnicastSubject.create<Error>()
-  override val error = _error.publish().refCount()
-  private val _connectionError = ReusableUnicastSubject.create<Throwable>()
-  override val connectionError = _connectionError.publish().refCount()
+  private val __error = ReusableUnicastSubject.create<Error>()
+  private val __connectionError = ReusableUnicastSubject.create<Throwable>()
+  private val __initProgress = BehaviorSubject.createDefault(0 to 0)
+  override val progress = ISession.ProgressData(
+    coreConnection.state,
+    __initProgress,
+    __error.publish().refCount()
+  )
 
   override val aliasManager = AliasManager(this)
   override val backlogManager = BacklogManager(this, backlogStorage)
@@ -105,8 +108,6 @@ class Session(
 
   override val rpcHandler = RpcHandler(this, backlogStorage, notificationManager)
 
-  override val initStatus = BehaviorSubject.createDefault(0 to 0)
-
   override val lag = BehaviorSubject.createDefault(0L)
 
   private val heartBeatThread = heartBeatFactory()
@@ -120,7 +121,7 @@ class Session(
 
   private fun handleError(error: Error) {
     hasErroredCallback?.invoke(error)
-    _error.onNext(error)
+    __error.onNext(error)
   }
 
   override fun handle(f: HandshakeMessage.ClientInitAck): Boolean {
@@ -177,7 +178,7 @@ class Session(
   }
 
   fun handleConnectionError(connectionError: Throwable) {
-    _connectionError.onNext(connectionError)
+    __connectionError.onNext(connectionError)
   }
 
   override fun addNetwork(networkId: NetworkId) {
@@ -261,7 +262,7 @@ class Session(
   }
 
   override fun onInitStatusChanged(progress: Int, total: Int) {
-    initStatus.onNext(progress to total)
+    __initProgress.onNext(Pair(progress, total))
   }
 
   override fun onInitDone() {
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 27a4c6415a84135b099a5ea5edb009e3d60e24b8..0966dc639d35bbeae70ae2220244d7f6b133f668 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
@@ -20,20 +20,18 @@
 package de.kuschku.libquassel.session
 
 import de.kuschku.libquassel.connection.ConnectionState
-import de.kuschku.libquassel.connection.HostnameVerifier
-import de.kuschku.libquassel.connection.SocketAddress
-import de.kuschku.libquassel.protocol.ClientData
 import de.kuschku.libquassel.protocol.message.HandshakeMessage
 import de.kuschku.libquassel.quassel.syncables.interfaces.invokers.Invokers
+import de.kuschku.libquassel.session.manager.ConnectionInfo
+import de.kuschku.libquassel.session.manager.SessionState
 import de.kuschku.libquassel.util.compatibility.HandlerService
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.*
-import de.kuschku.libquassel.util.helpers.or
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.or
+import de.kuschku.libquassel.util.helper.value
 import io.reactivex.Observable
 import io.reactivex.disposables.Disposable
-import io.reactivex.functions.BiFunction
-import io.reactivex.subjects.BehaviorSubject
-import javax.net.ssl.X509TrustManager
 
 class SessionManager(
   offlineSession: ISession,
@@ -42,7 +40,21 @@ class SessionManager(
   val handlerService: HandlerService,
   private val heartBeatFactory: () -> HeartBeatRunner,
   private val exceptionHandler: (Throwable) -> Unit
-) {
+) : SessionStateHandler(SessionState(offlineSession, null, null)) {
+  // Stateful fields
+  private var lastConnectionInfo: ConnectionInfo? = null
+  private var hasErrored: Boolean = false
+
+  private val disposables = mutableListOf<Disposable>()
+
+  // Helping Rx Mappers
+  val connectionProgress: Observable<Triple<ConnectionState, Int, Int>> = progressData.switchMap {
+    combineLatest(it.state, it.progress).map { (state, progress) ->
+      Triple(state, progress.first, progress.second)
+    }
+  }
+
+  // Listeners
   private var disconnectFromCore: (() -> Unit)? = null
   private var initCallback: ((Session) -> Unit)? = null
 
@@ -54,52 +66,12 @@ class SessionManager(
     this.initCallback = callback
   }
 
-  fun close() = session.or(lastSession).close()
-
-  data class ConnectionInfo(
-    val clientData: ClientData,
-    val trustManager: X509TrustManager,
-    val hostnameVerifier: HostnameVerifier,
-    val address: SocketAddress,
-    val userData: Pair<String, String>,
-    val requireSsl: Boolean,
-    val shouldReconnect: Boolean
-  )
-
-  private var lastConnectionInfo: ConnectionInfo? = null
-
-  private var inProgressSession = BehaviorSubject.createDefault(ISession.NULL)
-  private var lastSession: ISession = offlineSession
-  val state: Observable<ConnectionState> = inProgressSession.switchMap(ISession::state)
-
-  private val initStatus: Observable<Pair<Int, Int>> = inProgressSession.switchMap(ISession::initStatus)
-  val session: Observable<ISession> = state.map { connectionState ->
-    if (connectionState == ConnectionState.CONNECTED)
-      inProgressSession.value
-    else
-      lastSession
-  }
-
-  private var hasErrored: Boolean = false
-
-  val error = inProgressSession.switchMap(ISession::error)
-
-  val connectionError = inProgressSession.switchMap(ISession::connectionError)
-
-  val connectionProgress: Observable<Triple<ConnectionState, Int, Int>> = Observable.combineLatest(
-    state, initStatus,
-    BiFunction<ConnectionState, Pair<Int, Int>, Triple<ConnectionState, Int, Int>> { t1, t2 ->
-      Triple(t1, t2.first, t2.second)
-    })
-
-  val disposables = mutableListOf<Disposable>()
-
   init {
     log(INFO, "Session", "Session created")
 
-    disposables.add(state.subscribe {
+    disposables.add(state.distinctUntilChanged().subscribe {
       if (it == ConnectionState.CONNECTED) {
-        lastSession.close()
+        updateStateConnected()
       }
     })
 
@@ -108,38 +80,35 @@ class SessionManager(
   }
 
   fun login(user: String, pass: String) {
-    inProgressSession.value.login(user, pass)
+    connectingSession.value?.login(user, pass)
   }
 
   fun setupCore(setupData: HandshakeMessage.CoreSetupData) {
-    inProgressSession.value.setupCore(setupData)
+    connectingSession.value?.setupCore(setupData)
   }
 
   fun connect(
     connectionInfo: ConnectionInfo
   ) {
     log(DEBUG, "SessionManager", "Connecting")
-    inProgressSession.value.close()
     lastConnectionInfo = connectionInfo
     hasErrored = false
-    inProgressSession.onNext(
-      Session(
-        connectionInfo.address,
-        connectionInfo.userData,
-        connectionInfo.requireSsl,
-        connectionInfo.trustManager,
-        connectionInfo.hostnameVerifier,
-        connectionInfo.clientData,
-        handlerService,
-        heartBeatFactory,
-        disconnectFromCore,
-        initCallback,
-        exceptionHandler,
-        ::hasErroredCallback,
-        notificationManager,
-        backlogStorage
-      )
-    )
+    updateStateConnecting(Session(
+      connectionInfo.address,
+      connectionInfo.userData,
+      connectionInfo.requireSsl,
+      connectionInfo.trustManager,
+      connectionInfo.hostnameVerifier,
+      connectionInfo.clientData,
+      handlerService,
+      heartBeatFactory,
+      disconnectFromCore,
+      initCallback,
+      exceptionHandler,
+      ::hasErroredCallback,
+      notificationManager,
+      backlogStorage
+    ))
   }
 
   fun hasErroredCallback(error: Error) {
@@ -147,52 +116,41 @@ class SessionManager(
     hasErrored = true
   }
 
-  /**
-   * @return if an autoreconnect has been necessary
-   */
-  fun autoReconnect(forceReconnect: Boolean = false) = if (!hasErrored) {
-    state.or(ConnectionState.DISCONNECTED).let {
-      if (it == ConnectionState.CLOSED) {
-        log(INFO, "SessionManager", "Autoreconnect triggered")
-        reconnect(forceReconnect)
-        true
-      } else {
-        log(INFO, "SessionManager", "Autoreconnect failed: state is $it")
-        false
-      }
+  fun autoConnect(
+    ignoreConnectionState: Boolean = false,
+    ignoreSetting: Boolean = false,
+    ignoreErrors: Boolean = false,
+    connectionInfo: ConnectionInfo? = lastConnectionInfo
+  ): Boolean {
+    if (connectionInfo == null) {
+      log(INFO, "SessionManager", "Reconnect failed: not enough data available")
+      return false
     }
-  } else {
-    log(INFO, "SessionManager", "Autoreconnect failed: hasErrored")
-    false
-  }
-
-  fun reconnect(forceReconnect: Boolean = false) {
-    if (lastConnectionInfo?.shouldReconnect == true || forceReconnect) {
-      val connectionInfo = lastConnectionInfo
 
-      if (connectionInfo != null) {
-        connect(connectionInfo)
-      } else {
-        log(INFO, "SessionManager", "Reconnect failed: not enough data available")
-      }
-    } else {
+    if (!connectionInfo.shouldReconnect && !ignoreSetting) {
       log(INFO, "SessionManager", "Reconnect failed: reconnect not allowed")
+      return false
     }
-  }
 
-  fun disconnect(forever: Boolean) {
-    if (forever)
-      backlogStorage.clearMessages()
-    inProgressSession.value.close()
-    inProgressSession.onNext(ISession.NULL)
-  }
+    val connectionState = state.or(ConnectionState.DISCONNECTED)
+    if (connectionState != ConnectionState.DISCONNECTED && !ignoreConnectionState) {
+      log(INFO, "SessionManager", "Reconnect failed: connection state is $connectionState")
+      return false
+    }
 
-  fun ifDisconnected(closure: (ISession) -> Unit) {
-    state.or(ConnectionState.DISCONNECTED).let {
-      if (it == ConnectionState.CLOSED || it == ConnectionState.DISCONNECTED) {
-        closure(inProgressSession.value)
-      }
+    if (hasErrored && !ignoreErrors) {
+      log(INFO, "SessionManager", "Reconnect failed: errors have been thrown")
+      return false
     }
+
+    log(INFO, "SessionManager", "Reconnect successful")
+    connect(connectionInfo)
+    return true
+  }
+
+  fun disconnect(forever: Boolean) {
+    if (forever) backlogStorage.clearMessages()
+    updateStateOffline()
   }
 
   fun dispose() {
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/SessionStateHandler.kt b/lib/src/main/java/de/kuschku/libquassel/session/SessionStateHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8a5ea7efbef5b1d093231b308f6f1e8ca652e8da
--- /dev/null
+++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionStateHandler.kt
@@ -0,0 +1,76 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * 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.session
+
+import de.kuschku.libquassel.session.manager.SessionState
+import io.reactivex.subjects.BehaviorSubject
+
+open class SessionStateHandler constructor(
+  initialState: SessionState
+) {
+  private val sessions = BehaviorSubject.createDefault(initialState)
+
+  val connectedSession = sessions.map {
+    it.connected
+    ?: it.offline
+  }
+
+  val connectingSession = sessions.map {
+    it.connecting
+    ?: it.connected
+    ?: it.offline
+  }
+
+  val progressData = connectingSession.map {
+    it.progress
+  }
+
+  val errors = progressData.switchMap {
+    it.error
+  }
+
+  val progress = progressData.switchMap {
+    it.progress
+  }
+
+  val state = progressData.switchMap {
+    it.state
+  }
+
+  private fun updateState(f: SessionState.() -> SessionState) {
+    sessions.onNext(f(sessions.value))
+  }
+
+  protected fun updateStateConnecting(connectingSession: ISession) = updateState {
+    connecting?.close()
+    copy(connecting = connectingSession)
+  }
+
+  protected fun updateStateConnected() = updateState {
+    connected?.close()
+    copy(connected = connecting, connecting = null)
+  }
+
+  protected fun updateStateOffline() = updateState {
+    connected?.close()
+    connecting?.close()
+    copy(connecting = null, connected = null)
+  }
+}
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/manager/ConnectionInfo.kt b/lib/src/main/java/de/kuschku/libquassel/session/manager/ConnectionInfo.kt
new file mode 100644
index 0000000000000000000000000000000000000000..aa7f9f8eeea8511746075ce7bfd25f9a24bd2499
--- /dev/null
+++ b/lib/src/main/java/de/kuschku/libquassel/session/manager/ConnectionInfo.kt
@@ -0,0 +1,35 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * 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.session.manager
+
+import de.kuschku.libquassel.connection.HostnameVerifier
+import de.kuschku.libquassel.connection.SocketAddress
+import de.kuschku.libquassel.protocol.ClientData
+import javax.net.ssl.X509TrustManager
+
+data class ConnectionInfo(
+  val clientData: ClientData,
+  val trustManager: X509TrustManager,
+  val hostnameVerifier: HostnameVerifier,
+  val address: SocketAddress,
+  val userData: Pair<String, String>,
+  val requireSsl: Boolean,
+  val shouldReconnect: Boolean
+)
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/manager/SessionState.kt b/lib/src/main/java/de/kuschku/libquassel/session/manager/SessionState.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1f55044fa1068b68c9f2cb0e329c24a016eba340
--- /dev/null
+++ b/lib/src/main/java/de/kuschku/libquassel/session/manager/SessionState.kt
@@ -0,0 +1,28 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2019 Janne Koschinski
+ * Copyright (c) 2019 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * 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.session.manager
+
+import de.kuschku.libquassel.session.ISession
+
+data class SessionState(
+  val offline: ISession,
+  val connecting: ISession?,
+  val connected: ISession?
+)
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt
index 806e4d76d55e7660fe9b7927d12e5923d8d7a83d..e1b1520d3f79cffc539564e168ab85c98cda2446 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt
@@ -23,15 +23,15 @@ package de.kuschku.libquassel.util.compatibility
 import de.kuschku.libquassel.util.compatibility.reference.JavaLoggingHandler
 
 abstract class LoggingHandler {
-  abstract fun log(logLevel: LogLevel, tag: String, message: String? = null,
-                   throwable: Throwable? = null)
+  abstract fun _log(logLevel: LogLevel, tag: String, message: String? = null,
+                    throwable: Throwable? = null)
 
-  abstract fun isLoggable(logLevel: LogLevel, tag: String): Boolean
+  abstract fun _isLoggable(logLevel: LogLevel, tag: String): Boolean
   inline fun isLoggable(logLevel: LogLevel, tag: String, f: LogContext.() -> Unit) {
-    if (isLoggable(logLevel, tag)) {
+    if (_isLoggable(logLevel, tag)) {
       object : LogContext {
         override fun log(message: String?, throwable: Throwable?) {
-          this@LoggingHandler.log(logLevel, tag, message, throwable)
+          this@LoggingHandler._log(logLevel, tag, message, throwable)
         }
       }.f()
     }
@@ -53,17 +53,17 @@ abstract class LoggingHandler {
   companion object {
     val loggingHandlers: MutableSet<LoggingHandler> = mutableSetOf(JavaLoggingHandler)
 
-    inline fun log(logLevel: LoggingHandler.LogLevel, tag: String, message: String?,
+    inline fun log(logLevel: LogLevel, tag: String, message: String?,
                    throwable: Throwable?) {
-      LoggingHandler.loggingHandlers
-        .filter { it.isLoggable(logLevel, tag) }
-        .forEach { it.log(logLevel, tag, message, throwable) }
+      loggingHandlers
+        .filter { it._isLoggable(logLevel, tag) }
+        .forEach { it._log(logLevel, tag, message, throwable) }
     }
 
-    inline fun log(logLevel: LoggingHandler.LogLevel, tag: String, throwable: Throwable) =
+    inline fun log(logLevel: LogLevel, tag: String, throwable: Throwable) =
       log(logLevel, tag, null, throwable)
 
-    inline fun log(logLevel: LoggingHandler.LogLevel, tag: String, message: String) =
+    inline fun log(logLevel: LogLevel, tag: String, message: String) =
       log(logLevel, tag, message, null)
   }
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/reference/JavaLoggingHandler.kt b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/reference/JavaLoggingHandler.kt
index 08da6f1c45cb803f5a508e3ae53e9f5560039f3a..4d2d75ac891c24455397990b60467b27368fc5a2 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/reference/JavaLoggingHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/reference/JavaLoggingHandler.kt
@@ -24,13 +24,13 @@ import java.util.logging.Level
 import java.util.logging.Logger
 
 object JavaLoggingHandler : LoggingHandler() {
-  override fun isLoggable(logLevel: LogLevel, tag: String): Boolean {
+  override fun _isLoggable(logLevel: LogLevel, tag: String): Boolean {
     return Logger.getLogger(tag).isLoggable(
       priority(logLevel)
     )
   }
 
-  override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
+  override fun _log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
     val priority = priority(
       logLevel
     )
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/flag/Flag.kt b/lib/src/main/java/de/kuschku/libquassel/util/flag/Flag.kt
index c1b40a8a4322608e833f1a62993e76a2bc2a0cbd..84c119221b5918f971575e30771f713b708ed102 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/flag/Flag.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/flag/Flag.kt
@@ -19,7 +19,7 @@
 
 package de.kuschku.libquassel.util.flag
 
-import de.kuschku.libquassel.util.helpers.sum
+import de.kuschku.libquassel.util.helper.sum
 import java.io.Serializable
 
 interface Flag<T> : Serializable where T : Enum<T>, T : Flag<T> {
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/flag/LongFlag.kt b/lib/src/main/java/de/kuschku/libquassel/util/flag/LongFlag.kt
index ce5deff1e0484a636babf64e7221ee4ec4ff0a85..f10d6469072e067c6c0473ab8531118ab3b268e9 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/flag/LongFlag.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/flag/LongFlag.kt
@@ -19,7 +19,7 @@
 
 package de.kuschku.libquassel.util.flag
 
-import de.kuschku.libquassel.util.helpers.sum
+import de.kuschku.libquassel.util.helper.sum
 import java.io.Serializable
 
 interface LongFlag<T> : Serializable where T : Enum<T>, T : LongFlag<T> {
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/flag/ShortFlag.kt b/lib/src/main/java/de/kuschku/libquassel/util/flag/ShortFlag.kt
index 8369662f70b59936d39a3ddc4371ef7df86a26ea..fbfe36b9c51cda8e7cb6a87396d9f322af5b4bb5 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/flag/ShortFlag.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/flag/ShortFlag.kt
@@ -19,7 +19,7 @@
 
 package de.kuschku.libquassel.util.flag
 
-import de.kuschku.libquassel.util.helpers.sum
+import de.kuschku.libquassel.util.helper.sum
 import java.io.Serializable
 
 interface ShortFlag<T> : Serializable where T : Enum<T>, T : ShortFlag<T> {
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/AnyHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/AnyHelper.kt
similarity index 94%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/AnyHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/AnyHelper.kt
index eac352e8d304b9e30cb081e00171d26915ef5915..abac540997842db1399b609a445125016ce7e919 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/AnyHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/AnyHelper.kt
@@ -17,6 +17,6 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 inline fun <T> T.nullIf(f: (T) -> Boolean): T? = if (f(this)) null else this
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ArrayHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/ArrayHelper.kt
similarity index 96%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/ArrayHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/ArrayHelper.kt
index 0cad4c36f8df288efb1e5d4ace8cb89a8a730ab1..fa359979dd064d48c5d21b0e249e00d00a3b13b4 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ArrayHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/ArrayHelper.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.WARN
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ByteBufferHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/ByteBufferHelper.kt
similarity index 96%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/ByteBufferHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/ByteBufferHelper.kt
index 88ca0e7d696534520a49c913d0d4acf7d10de3ac..cf150ebb015b62e9c6484874cd7c970d3babe63a 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ByteBufferHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/ByteBufferHelper.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
 import java.nio.ByteBuffer
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/CollectionHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/CollectionHelper.kt
similarity index 97%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/CollectionHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/CollectionHelper.kt
index 762ee9808b143d472450e693ac8a7ce41a6a8115..5aa07825ce683f2185c841f8620b364690260952 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/CollectionHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/CollectionHelper.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 
 /**
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/MapHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/MapHelper.kt
similarity index 95%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/MapHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/MapHelper.kt
index 1c160581499f7fa9148f48d49e1584a7ad73865d..7d1d0a1cadf9485be87f305533661180755aa5fa 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/MapHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/MapHelper.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 fun <K, V> Map<K, V>.getOr(key: K, defValue: V) = this[key] ?: defValue
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/MathHelper.kt
similarity index 95%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/MathHelper.kt
index be6b40224d39309e515ab51055d390a8da8aa37c..e75d1997528b8386d5ca9675103c6648dd7d66af 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/MathHelper.kt
@@ -18,7 +18,7 @@
  */
 @file:Suppress("NOTHING_TO_INLINE")
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 inline fun clampOf(value: Int, lowerBound: Int, upperBound: Int): Int =
   maxOf(lowerBound, minOf(value, upperBound))
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/ObservableHelper.kt
similarity index 50%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/ObservableHelper.kt
index 310b5effc81f2b34c94b1a076ca1e9565682e23d..2743979f649c0d11a144a8555b2393c7de777abe 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/ObservableHelper.kt
@@ -17,10 +17,12 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 import de.kuschku.libquassel.util.Optional
 import io.reactivex.Observable
+import io.reactivex.ObservableSource
+import io.reactivex.functions.BiFunction
 
 fun <T> Observable<T>.or(default: T): T = try {
   this.blockingLatest().firstOrNull() ?: default
@@ -70,3 +72,81 @@ fun <T : Any, U : Any> Observable<Optional<T>>.flatMapSwitchMap(
 fun <T : Any> Observable<Optional<T>>.mapOrElse(orElse: T): Observable<T> = map {
   it.orElse(orElse)
 }
+
+inline fun <reified A, B> combineLatest(
+  a: ObservableSource<A>,
+  b: ObservableSource<B>
+): Observable<Pair<A, B>> =
+  Observable.combineLatest(a, b, BiFunction(::Pair))
+
+inline fun <reified A, B, C> combineLatest(
+  a: ObservableSource<A>,
+  b: ObservableSource<B>,
+  c: ObservableSource<C>
+): Observable<Triple<A, B, C>> =
+  Observable.combineLatest(listOf(a, b, c)) {
+    Triple(it[0], it[1], it[2]) as Triple<A, B, C>
+  }
+
+inline fun <reified A, B, C, D> combineLatest(
+  a: ObservableSource<A>,
+  b: ObservableSource<B>,
+  c: ObservableSource<C>,
+  d: ObservableSource<D>
+): Observable<Tuple4<A, B, C, D>> =
+  Observable.combineLatest(listOf(a, b, c, d)) {
+    Tuple4(it[0], it[1], it[2], it[3]) as Tuple4<A, B, C, D>
+  }
+
+inline fun <reified A, B, C, D, E> combineLatest(
+  a: ObservableSource<A>,
+  b: ObservableSource<B>,
+  c: ObservableSource<C>,
+  d: ObservableSource<D>,
+  e: ObservableSource<E>
+): Observable<Tuple5<A, B, C, D, E>> =
+  Observable.combineLatest(listOf(a, b, c, d, e)) {
+    Tuple5(it[0], it[1], it[2], it[3], it[4]) as Tuple5<A, B, C, D, E>
+  }
+
+inline fun <reified A, B, C, D, E, F> combineLatest(
+  a: ObservableSource<A>,
+  b: ObservableSource<B>,
+  c: ObservableSource<C>,
+  d: ObservableSource<D>,
+  e: ObservableSource<E>,
+  f: ObservableSource<F>
+): Observable<Tuple6<A, B, C, D, E, F>> =
+  Observable.combineLatest(listOf(a, b, c, d, e, f)) {
+    Tuple6(it[0], it[1], it[2], it[3], it[4], it[5]) as Tuple6<A, B, C, D, E, F>
+  }
+
+inline fun <reified T> combineLatest(sources: Iterable<ObservableSource<out T>?>) =
+  Observable.combineLatest(sources) { t -> t.toList() as List<T> }
+
+inline operator fun <T, U> Observable<T>.invoke(f: (T) -> U?) =
+  blockingLatest().firstOrNull()?.let(f)
+
+data class Tuple4<out A, out B, out C, out D>(
+  val first: A,
+  val second: B,
+  val third: C,
+  val fourth: D
+)
+
+data class Tuple5<out A, out B, out C, out D, out E>(
+  val first: A,
+  val second: B,
+  val third: C,
+  val fourth: D,
+  val fifth: E
+)
+
+data class Tuple6<out A, out B, out C, out D, out E, out F>(
+  val first: A,
+  val second: B,
+  val third: C,
+  val fourth: D,
+  val fifth: E,
+  val sixth: F
+)
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/StringHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/StringHelper.kt
similarity index 96%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/StringHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/StringHelper.kt
index 30ee8c52a5be24fad28507d5e140e3ca0579ae40..81a0c7d69e3d3cae9fb996fda94540c64c6cacde 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/StringHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/StringHelper.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/WritableByteChannelHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helper/WritableByteChannelHelper.kt
similarity index 95%
rename from lib/src/main/java/de/kuschku/libquassel/util/helpers/WritableByteChannelHelper.kt
rename to lib/src/main/java/de/kuschku/libquassel/util/helper/WritableByteChannelHelper.kt
index 59d3e7fdc48ce5d076f44d890c1a477cfdda91de..0f89d9a9838a5f864e4b65c4eaf7d0be5fa88fe7 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/WritableByteChannelHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helper/WritableByteChannelHelper.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.util.helpers
+package de.kuschku.libquassel.util.helper
 
 import de.kuschku.libquassel.util.nio.ChainedByteBuffer
 import java.nio.channels.WritableByteChannel
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/Backend.kt
similarity index 68%
rename from lib/src/main/java/de/kuschku/libquassel/session/Backend.kt
rename to viewmodel/src/main/java/de/kuschku/quasseldroid/Backend.kt
index ac5985ecc02c92273dbb851297f5efdbcc7ca655..873396569799b51b995febf66591073b56b11881 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/Backend.kt
@@ -17,20 +17,29 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.session
+package de.kuschku.quasseldroid
 
 import de.kuschku.libquassel.connection.SocketAddress
+import de.kuschku.libquassel.session.SessionManager
 
 interface Backend {
-  fun connectUnlessConnected(address: SocketAddress, user: String, pass: String,
-                             requireSsl: Boolean, reconnect: Boolean)
+  fun autoConnect(
+    ignoreConnectionState: Boolean = false,
+    ignoreSetting: Boolean = false,
+    ignoreErrors: Boolean = false,
+    connectionInfo: ConnectionInfo? = null
+  )
 
-  fun connect(address: SocketAddress, user: String, pass: String, requireSsl: Boolean,
-              reconnect: Boolean)
-
-  fun reconnect()
   fun disconnect(forever: Boolean = false)
   fun sessionManager(): SessionManager?
   fun updateUserDataAndLogin(user: String, pass: String)
   fun requestConnectNewNetwork()
+
+  data class ConnectionInfo(
+    val address: SocketAddress,
+    val username: String,
+    val password: String,
+    val requireSsl: Boolean,
+    val shouldReconnect: Boolean
+  )
 }
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt
index 461f5fe6f05873af756341a5a829d686abf35920..29fcde0958fc0b30ae0634794a6672c04cb7fa41 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt
@@ -24,7 +24,6 @@ import androidx.lifecycle.LiveData
 import androidx.lifecycle.LiveDataReactiveStreams
 import de.kuschku.libquassel.util.compatibility.HandlerService
 import io.reactivex.*
-import io.reactivex.functions.BiFunction
 import io.reactivex.schedulers.Schedulers
 
 inline fun <T> Observable<T>.toLiveData(
@@ -44,81 +43,3 @@ inline fun <T> Flowable<T>.toLiveData(
   handlerService: HandlerService? = null,
   scheduler: Scheduler = handlerService?.scheduler ?: Schedulers.computation()
 ): LiveData<T> = LiveDataReactiveStreams.fromPublisher(subscribeOn(scheduler))
-
-inline fun <reified A, B> combineLatest(
-  a: ObservableSource<A>,
-  b: ObservableSource<B>
-): Observable<Pair<A, B>> =
-  Observable.combineLatest(a, b, BiFunction(::Pair))
-
-inline fun <reified A, B, C> combineLatest(
-  a: ObservableSource<A>,
-  b: ObservableSource<B>,
-  c: ObservableSource<C>
-): Observable<Triple<A, B, C>> =
-  Observable.combineLatest(listOf(a, b, c)) {
-    Triple(it[0], it[1], it[2]) as Triple<A, B, C>
-  }
-
-inline fun <reified A, B, C, D> combineLatest(
-  a: ObservableSource<A>,
-  b: ObservableSource<B>,
-  c: ObservableSource<C>,
-  d: ObservableSource<D>
-): Observable<Tuple4<A, B, C, D>> =
-  Observable.combineLatest(listOf(a, b, c, d)) {
-    Tuple4(it[0], it[1], it[2], it[3]) as Tuple4<A, B, C, D>
-  }
-
-inline fun <reified A, B, C, D, E> combineLatest(
-  a: ObservableSource<A>,
-  b: ObservableSource<B>,
-  c: ObservableSource<C>,
-  d: ObservableSource<D>,
-  e: ObservableSource<E>
-): Observable<Tuple5<A, B, C, D, E>> =
-  Observable.combineLatest(listOf(a, b, c, d, e)) {
-    Tuple5(it[0], it[1], it[2], it[3], it[4]) as Tuple5<A, B, C, D, E>
-  }
-
-inline fun <reified A, B, C, D, E, F> combineLatest(
-  a: ObservableSource<A>,
-  b: ObservableSource<B>,
-  c: ObservableSource<C>,
-  d: ObservableSource<D>,
-  e: ObservableSource<E>,
-  f: ObservableSource<F>
-): Observable<Tuple6<A, B, C, D, E, F>> =
-  Observable.combineLatest(listOf(a, b, c, d, e, f)) {
-    Tuple6(it[0], it[1], it[2], it[3], it[4], it[5]) as Tuple6<A, B, C, D, E, F>
-  }
-
-inline fun <reified T> combineLatest(sources: Iterable<ObservableSource<out T>?>) =
-  Observable.combineLatest(sources) { t -> t.toList() as List<T> }
-
-inline operator fun <T, U> Observable<T>.invoke(f: (T) -> U?) =
-  blockingLatest().firstOrNull()?.let(f)
-
-data class Tuple4<out A, out B, out C, out D>(
-  val first: A,
-  val second: B,
-  val third: C,
-  val fourth: D
-)
-
-data class Tuple5<out A, out B, out C, out D, out E>(
-  val first: A,
-  val second: B,
-  val third: C,
-  val fourth: D,
-  val fifth: E
-)
-
-data class Tuple6<out A, out B, out C, out D, out E, out F>(
-  val first: A,
-  val second: B,
-  val third: C,
-  val fourth: D,
-  val fifth: E,
-  val sixth: F
-)
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
index b18a60589b5e36c80e81268f186dba1196408ef0..8021a2bb992c7421593dc2edf1ef28990eade6ef 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
@@ -20,8 +20,8 @@
 package de.kuschku.quasseldroid.viewmodel
 
 import androidx.lifecycle.ViewModel
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.util.Optional
+import de.kuschku.quasseldroid.Backend
 import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ChatViewModelHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ChatViewModelHelper.kt
index 48a72a1283952065c64df7a892ae8e3b8a0172ca..0e6a0ba7284a1b6560acf397b00384ef219b240e 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ChatViewModelHelper.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/ChatViewModelHelper.kt
@@ -32,12 +32,8 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.libquassel.util.flag.and
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.libquassel.util.helpers.flatMapSwitchMap
-import de.kuschku.libquassel.util.helpers.mapNullable
-import de.kuschku.libquassel.util.helpers.mapSwitchMap
-import de.kuschku.libquassel.util.helpers.switchMapNullable
+import de.kuschku.libquassel.util.helper.*
 import de.kuschku.libquassel.util.irc.IrcCaseMappers
-import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.viewmodel.ChatViewModel
 import de.kuschku.quasseldroid.viewmodel.QuasselViewModel
 import de.kuschku.quasseldroid.viewmodel.data.*
@@ -63,14 +59,14 @@ open class ChatViewModelHelper @Inject constructor(
   /**
    * An observable of the changes of the markerline, as pairs of `(old, new)`
    */
-  val markerLine = session.mapSwitchMap { currentSession ->
+  val markerLine = connectedSession.mapSwitchMap { currentSession ->
     chat.bufferId.switchMap { currentBuffer ->
       // Get a stream of the latest marker line
       currentSession.bufferSyncer.liveMarkerLine(currentBuffer)
     }
   }
 
-  val bufferData = combineLatest(session, chat.bufferId)
+  val bufferData = combineLatest(connectedSession, chat.bufferId)
     .switchMap { (sessionOptional, id) ->
       val session = sessionOptional.orNull()
       val bufferSyncer = session?.bufferSyncer
@@ -135,7 +131,7 @@ open class ChatViewModelHelper @Inject constructor(
   val bufferDataThrottled =
     bufferData.distinctUntilChanged().throttleLast(100, TimeUnit.MILLISECONDS)
 
-  val nickData: Observable<List<IrcUserItem>> = combineLatest(session, chat.bufferId)
+  val nickData: Observable<List<IrcUserItem>> = combineLatest(connectedSession, chat.bufferId)
     .switchMap { (sessionOptional, buffer) ->
       val session = sessionOptional.orNull()
       val bufferSyncer = session?.bufferSyncer
@@ -179,7 +175,7 @@ open class ChatViewModelHelper @Inject constructor(
   val nickDataThrottled =
     nickData.distinctUntilChanged().throttleLast(100, TimeUnit.MILLISECONDS)
 
-  val selectedBuffer = combineLatest(session, chat.selectedBufferId, bufferViewConfig)
+  val selectedBuffer = combineLatest(connectedSession, chat.selectedBufferId, bufferViewConfig)
     .switchMap { (sessionOptional, buffer, bufferViewConfigOptional) ->
       val session = sessionOptional.orNull()
       val bufferSyncer = session?.bufferSyncer
@@ -238,7 +234,7 @@ open class ChatViewModelHelper @Inject constructor(
     }
 
   val bufferList: Observable<Pair<BufferViewConfig?, List<BufferProps>>> =
-    combineLatest(session, bufferViewConfig, chat.showHidden, chat.bufferSearch)
+    combineLatest(connectedSession, bufferViewConfig, chat.showHidden, chat.bufferSearch)
       .switchMap { (sessionOptional, configOptional, showHiddenRaw, bufferSearch) ->
         val session = sessionOptional.orNull()
         val bufferSyncer = session?.bufferSyncer
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/EditorViewModelHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/EditorViewModelHelper.kt
index ebe446511ca95b8f6dcd74834d5b7db5b28ba819..a4d4200c8e262238795d838cdbfe0170320f8213 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/EditorViewModelHelper.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/EditorViewModelHelper.kt
@@ -28,9 +28,9 @@ import de.kuschku.libquassel.quassel.syncables.Network
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.libquassel.util.flag.hasFlag
-import de.kuschku.libquassel.util.helpers.mapNullable
-import de.kuschku.libquassel.util.helpers.nullIf
-import de.kuschku.quasseldroid.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.combineLatest
+import de.kuschku.libquassel.util.helper.mapNullable
+import de.kuschku.libquassel.util.helper.nullIf
 import de.kuschku.quasseldroid.viewmodel.ChatViewModel
 import de.kuschku.quasseldroid.viewmodel.EditorViewModel
 import de.kuschku.quasseldroid.viewmodel.QuasselViewModel
@@ -46,15 +46,14 @@ open class EditorViewModelHelper @Inject constructor(
   quassel: QuasselViewModel
 ) : ChatViewModelHelper(chat, quassel) {
   val rawAutoCompleteData: Observable<Triple<Optional<ISession>, BufferId, Pair<String, IntRange>>> =
-    combineLatest(session,
-                  chat.bufferId,
-                  editor.lastWord).switchMap { (sessionOptional, id, lastWordWrapper) ->
-      lastWordWrapper
-        .distinctUntilChanged()
-        .map { lastWord ->
-          Triple(sessionOptional, id, lastWord)
-        }
-    }
+    combineLatest(connectedSession, chat.bufferId, editor.lastWord)
+      .switchMap { (sessionOptional, id, lastWordWrapper) ->
+        lastWordWrapper
+          .distinctUntilChanged()
+          .map { lastWord ->
+            Triple(sessionOptional, id, lastWord)
+          }
+      }
 
   val autoCompleteData: Observable<Pair<String, List<AutoCompleteItem>>> = rawAutoCompleteData
     .distinctUntilChanged()
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/QuasselViewModelHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/QuasselViewModelHelper.kt
index 4159c5a67b79248a7b550f10a48b3ee1a926cb37..ad9184a4d6354b25543532137f2a04821573130a 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/QuasselViewModelHelper.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/helper/QuasselViewModelHelper.kt
@@ -25,12 +25,12 @@ import de.kuschku.libquassel.protocol.BufferId
 import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.quassel.syncables.BufferViewConfig
 import de.kuschku.libquassel.quassel.syncables.CoreInfo
-import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.session.ISession
 import de.kuschku.libquassel.session.SessionManager
 import de.kuschku.libquassel.ssl.X509Helper
 import de.kuschku.libquassel.util.Optional
-import de.kuschku.libquassel.util.helpers.*
+import de.kuschku.libquassel.util.helper.*
+import de.kuschku.quasseldroid.Backend
 import de.kuschku.quasseldroid.viewmodel.QuasselViewModel
 import io.reactivex.Observable
 import javax.inject.Inject
@@ -41,15 +41,15 @@ open class QuasselViewModelHelper @Inject constructor(
 ) {
   val backend = quassel.backendWrapper.switchMap { it }
   val sessionManager = backend.mapMapNullable(Backend::sessionManager)
-  val session = sessionManager.mapSwitchMap(SessionManager::session)
-  val rpcHandler = session.mapMap(ISession::rpcHandler)
-  val ircListHelper = session.mapMap(ISession::ircListHelper)
+  val connectedSession = sessionManager.mapSwitchMap(SessionManager::connectedSession)
+  val rpcHandler = connectedSession.mapMap(ISession::rpcHandler)
+  val ircListHelper = connectedSession.mapMap(ISession::ircListHelper)
   val features = sessionManager.mapSwitchMap { manager ->
     manager.state.switchMap { state ->
       if (state != ConnectionState.CONNECTED) {
         Observable.just(Pair(false, Features.empty()))
       } else {
-        manager.session.map {
+        manager.connectedSession.map {
           Pair(true, it.features)
         }
       }
@@ -68,48 +68,44 @@ open class QuasselViewModelHelper @Inject constructor(
   val connectionProgress = sessionManager.mapSwitchMap(SessionManager::connectionProgress)
     .mapOrElse(Triple(ConnectionState.DISCONNECTED, 0, 0))
 
-  val bufferViewManager = session.mapMap(ISession::bufferViewManager)
+  val bufferViewManager = connectedSession.mapMap(ISession::bufferViewManager)
 
   val errors = sessionManager.switchMap {
-    it.orNull()?.error ?: Observable.empty()
+    it.orNull()?.errors ?: Observable.empty()
   }
 
-  val connectionErrors = sessionManager.switchMap {
-    it.orNull()?.connectionError ?: Observable.empty()
-  }
-
-  val sslSession = session.flatMapSwitchMap(ISession::sslSession)
+  val sslSession = connectedSession.flatMapSwitchMap(ISession::sslSession)
   val peerCertificateChain = sslSession.mapMap(SSLSession::getPeerCertificateChain).mapMap {
     it.mapNotNull(X509Helper::convert)
   }.mapOrElse(emptyList())
   val leafCertificate = peerCertificateChain.map { Optional.ofNullable(it.firstOrNull()) }
 
-  val coreInfo = session.mapMap(ISession::coreInfo).mapSwitchMap(CoreInfo::liveInfo)
+  val coreInfo = connectedSession.mapMap(ISession::coreInfo).mapSwitchMap(CoreInfo::liveInfo)
   val coreInfoClients = coreInfo.mapMap(CoreInfo.CoreData::sessionConnectedClientData)
     .mapOrElse(emptyList())
 
-  val networkConfig = session.mapMap(ISession::networkConfig)
+  val networkConfig = connectedSession.mapMap(ISession::networkConfig)
 
-  val ignoreListManager = session.mapMap(ISession::ignoreListManager)
+  val ignoreListManager = connectedSession.mapMap(ISession::ignoreListManager)
 
-  val highlightRuleManager = session.mapMap(ISession::highlightRuleManager)
+  val highlightRuleManager = connectedSession.mapMap(ISession::highlightRuleManager)
 
-  val aliasManager = session.mapMap(ISession::aliasManager)
+  val aliasManager = connectedSession.mapMap(ISession::aliasManager)
 
-  val networks = session.switchMap {
+  val networks = connectedSession.switchMap {
     it.map(ISession::liveNetworks).orElse(Observable.just(emptyMap()))
   }
 
-  val identities = session.switchMap {
+  val identities = connectedSession.switchMap {
     it.map(ISession::liveIdentities).orElse(Observable.just(emptyMap()))
   }
 
-  val bufferSyncer = session.mapMap(ISession::bufferSyncer)
+  val bufferSyncer = connectedSession.mapMap(ISession::bufferSyncer)
   val allBuffers = bufferSyncer.mapSwitchMap {
     it.liveBufferInfos().map(Map<BufferId, BufferInfo>::values)
   }.mapOrElse(emptyList())
 
-  val lag: Observable<Long> = session.mapSwitchMap(ISession::lag).mapOrElse(0)
+  val lag: Observable<Long> = connectedSession.mapSwitchMap(ISession::lag).mapOrElse(0)
 
   val bufferViewConfigs = bufferViewManager.mapSwitchMap { manager ->
     manager.liveBufferViewConfigs().map { ids ->