diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index bbdc960c58c557e2b4e8e3780076d58e161bde19..56d1cf8664272f224d9636c58174525305126dfc 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -105,7 +105,7 @@ android {
 
   lintOptions {
     isWarningsAsErrors = true
-    setLintConfig(file("../lint.xml"))
+    lintConfig = file("../lint.xml")
   }
 }
 
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 7d5ccb03b543cdfae3fa5a592a3bc1411b62554d..13bcc255cf187bd1bfa155e97aed017c2b2a5385 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
@@ -55,7 +55,6 @@ import de.kuschku.quasseldroid.ssl.custom.QuasselHostnameManager
 import de.kuschku.quasseldroid.util.backport.DaggerLifecycleService
 import de.kuschku.quasseldroid.util.compatibility.AndroidHandlerService
 import de.kuschku.quasseldroid.util.helper.*
-import de.kuschku.quasseldroid.util.irc.format.ContentFormatter
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatSerializer
 import de.kuschku.quasseldroid.util.ui.LocaleHelper
 import io.reactivex.subjects.PublishSubject
@@ -279,9 +278,6 @@ class QuasselService : DaggerLifecycleService(),
   @Inject
   lateinit var accountDatabase: AccountDatabase
 
-  @Inject
-  lateinit var contentFormatter: ContentFormatter
-
   @Inject
   lateinit var messageSettings: MessageSettings
 
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 9a7ef3470d60790a272022def0b95c62e1831dbc..8f4e1e819a2d970e8489e839f687420fbd27e5c0 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
@@ -26,7 +26,6 @@ import android.content.Intent
 import android.content.SharedPreferences
 import android.graphics.Bitmap
 import android.graphics.Canvas
-import android.graphics.Typeface
 import android.graphics.drawable.Drawable
 import android.os.Build
 import android.os.Bundle
@@ -75,6 +74,7 @@ import de.kuschku.quasseldroid.ui.clientsettings.client.ClientSettingsActivity
 import de.kuschku.quasseldroid.ui.coresettings.CoreSettingsActivity
 import de.kuschku.quasseldroid.ui.setup.accounts.selection.AccountSelectionActivity
 import de.kuschku.quasseldroid.ui.setup.user.UserSetupActivity
+import de.kuschku.quasseldroid.util.ColorContext
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
 import de.kuschku.quasseldroid.util.helper.*
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
@@ -83,7 +83,6 @@ import de.kuschku.quasseldroid.util.missingfeatures.RequiredFeatures
 import de.kuschku.quasseldroid.util.service.ServiceBoundActivity
 import de.kuschku.quasseldroid.util.ui.DragInterceptBottomSheetBehavior
 import de.kuschku.quasseldroid.util.ui.MaterialContentLoadingProgressBar
-import de.kuschku.quasseldroid.util.ui.TextDrawable
 import de.kuschku.quasseldroid.viewmodel.EditorViewModel
 import de.kuschku.quasseldroid.viewmodel.data.BufferData
 import org.threeten.bp.Instant
@@ -755,9 +754,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
             }
           }
 
-          val colorBackground = theme.styledAttributes(R.attr.colorBackground) {
-            getColor(0, 0)
-          }
+          val colorContext = ColorContext(this, messageSettings)
 
           if (info.type.hasFlag(Buffer_Type.QueryBuffer)) {
             val nickName = info.bufferName ?: ""
@@ -767,12 +764,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
             val initial = rawInitial?.toUpperCase().toString()
             val senderColor = senderColors[senderColorIndex]
 
-            val fallback = TextDrawable.builder()
-              .beginConfig()
-              .textColor((colorBackground and 0xFFFFFF) or (0x8A shl 24))
-              .useFont(Typeface.DEFAULT_BOLD)
-              .endConfig()
-              .buildRect(initial, senderColor)
+            val fallback = colorContext.prepareTextDrawable().buildRect(initial, senderColor)
 
             val urls = viewModel.networks.value?.get(info.networkId)?.ircUser(info.bufferName)?.let {
               AvatarHelper.avatar(messageSettings, it, 432)
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 dc7649ad2b996be753c2a74e5d1b8babd52e73f9..513990d250bc471c05da76c718db2be56adec8b0 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
@@ -20,7 +20,6 @@
 package de.kuschku.quasseldroid.ui.chat.buffers
 
 import android.arch.lifecycle.Observer
-import android.graphics.Typeface
 import android.os.Bundle
 import android.os.Parcelable
 import android.support.v7.widget.*
@@ -39,12 +38,12 @@ 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.value
-import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.persistence.QuasselDatabase
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.ui.coresettings.network.NetworkEditActivity
+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.styledAttributes
@@ -52,8 +51,6 @@ import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.helper.zip
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
 import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
-import de.kuschku.quasseldroid.util.ui.TextDrawable
-import de.kuschku.quasseldroid.viewmodel.EditorViewModel.Companion.IGNORED_CHARS
 import de.kuschku.quasseldroid.viewmodel.data.BufferHiddenState
 import de.kuschku.quasseldroid.viewmodel.data.BufferListItem
 import de.kuschku.quasseldroid.viewmodel.data.BufferState
@@ -259,20 +256,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
 
     val avatarSize = resources.getDimensionPixelSize(R.dimen.avatar_size_buffer)
 
-    val senderColors = requireContext().theme.styledAttributes(
-      R.attr.senderColor0, R.attr.senderColor1, R.attr.senderColor2, R.attr.senderColor3,
-      R.attr.senderColor4, R.attr.senderColor5, R.attr.senderColor6, R.attr.senderColor7,
-      R.attr.senderColor8, R.attr.senderColor9, R.attr.senderColorA, R.attr.senderColorB,
-      R.attr.senderColorC, R.attr.senderColorD, R.attr.senderColorE, R.attr.senderColorF
-    ) {
-      IntArray(length()) {
-        getColor(it, 0)
-      }
-    }
-
-    val selfColor = requireContext().theme.styledAttributes(R.attr.colorForegroundSecondary) {
-      getColor(0, 0)
-    }
+    val colorContext = ColorContext(requireContext(), messageSettings)
 
     val colorAccent = requireContext().theme.styledAttributes(R.attr.colorAccent) {
       getColor(0, 0)
@@ -282,12 +266,6 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
       getColor(0, 0)
     }
 
-    val colorBackground = requireContext().theme.styledAttributes(R.attr.colorBackground) {
-      getColor(0, 0)
-    }
-
-    val radius = requireContext().resources.getDimensionPixelSize(R.dimen.avatar_radius)
-
     combineLatest(viewModel.bufferList, viewModel.expandedNetworks, viewModel.selectedBuffer)
       .toLiveData().zip(database.filtered().listen(accountId))
       .observe(this, Observer { it ->
@@ -323,38 +301,20 @@ class BufferViewConfigFragment : ServiceBoundFragment() {
                   fallbackDrawable = if (props.info.type.hasFlag(Buffer_Type.QueryBuffer)) {
                     props.ircUser?.let {
                       val nickName = it.nick()
-                      val senderColorIndex = SenderColorUtil.senderColor(nickName)
-                      val rawInitial = nickName.trimStart(*IGNORED_CHARS).firstOrNull()
-                                       ?: nickName.firstOrNull()
-                      val initial = rawInitial?.toUpperCase().toString()
-                      val senderColor = when (messageSettings.colorizeNicknames) {
-                        MessageSettings.ColorizeNicknamesMode.ALL          -> senderColors[senderColorIndex]
+                      val useSelfColor = when (messageSettings.colorizeNicknames) {
+                        MessageSettings.ColorizeNicknamesMode.ALL          -> false
                         MessageSettings.ColorizeNicknamesMode.ALL_BUT_MINE ->
-                          if (props.ircUser?.network()?.isMyNick(nickName) == true) selfColor
-                          else senderColors[senderColorIndex]
-                        MessageSettings.ColorizeNicknamesMode.NONE         -> selfColor
+                          props.ircUser?.network()?.isMyNick(nickName) == true
+                        MessageSettings.ColorizeNicknamesMode.NONE         -> true
                       }
 
-                      TextDrawable.builder().beginConfig()
-                        .textColor((colorBackground and 0xFFFFFF) or (0x8A shl 24)).useFont(Typeface.DEFAULT_BOLD).endConfig().let {
-                          if (messageSettings.squareAvatars)
-                            it.buildRoundRect(initial, senderColor, radius)
-                          else it.buildRound(initial, senderColor)
-                        }
-                    }
-                    ?: TextDrawable.builder().beginConfig()
-                      .textColor((colorBackground and 0xFFFFFF) or (0x8A shl 24)).useFont(Typeface.DEFAULT_BOLD).endConfig().let {
-                        if (messageSettings.squareAvatars) it.buildRoundRect("", colorAway, radius)
-                        else it.buildRound("", colorAway)
-                      }
+                      colorContext.buildTextDrawable(it.nick(), useSelfColor)
+                    } ?: colorContext.buildTextDrawable("", colorAway)
                   } else {
                     val color = if (props.bufferStatus == BufferStatus.ONLINE) colorAccent
                     else colorAway
 
-                    TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT_BOLD).endConfig().let {
-                      if (messageSettings.squareAvatars) it.buildRoundRect("#", color, radius)
-                      else it.buildRound("#", color)
-                    }
+                    colorContext.buildTextDrawable("#", color)
                   },
                   avatarUrls = props.ircUser?.let {
                     AvatarHelper.avatar(messageSettings, it, avatarSize)
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 9f6cd378e98187cf6456a11a8d8b562ce384197e..7414e030ddbb511ad6b59d0ef31546f521b29742 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
@@ -38,11 +38,11 @@ import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
+import de.kuschku.quasseldroid.util.ColorContext
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
 import de.kuschku.quasseldroid.util.helper.styledAttributes
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
-import de.kuschku.quasseldroid.util.ui.TextDrawable
 import de.kuschku.quasseldroid.viewmodel.EditorViewModel
 import de.kuschku.quasseldroid.viewmodel.EditorViewModel.Companion.IGNORED_CHARS
 import de.kuschku.quasseldroid.viewmodel.data.AutoCompleteItem
@@ -81,11 +81,7 @@ class AutoCompleteHelper(
     getColor(0, 0)
   }
 
-  private val colorBackground = activity.theme.styledAttributes(R.attr.colorBackground) {
-    getColor(0, 0)
-  }
-
-  private val radius = activity.resources.getDimensionPixelSize(R.dimen.avatar_radius)
+  private val colorContext = ColorContext(activity, messageSettings)
 
   init {
     viewModel.autoCompleteData.toLiveData().observe(activity, Observer {
@@ -108,13 +104,12 @@ class AutoCompleteHelper(
             val rawInitial = nickName.trimStart(*IGNORED_CHARS).firstOrNull()
                              ?: nickName.firstOrNull()
             val initial = rawInitial?.toUpperCase().toString()
-            val senderColor = when (messageSettings.colorizeNicknames) {
-              MessageSettings.ColorizeNicknamesMode.ALL          -> senderColors[senderColorIndex]
-              MessageSettings.ColorizeNicknamesMode.ALL_BUT_MINE ->
-                if (it.self) selfColor
-                else senderColors[senderColorIndex]
-              MessageSettings.ColorizeNicknamesMode.NONE         -> selfColor
+            val useSelfColor = when (messageSettings.colorizeNicknames) {
+              MessageSettings.ColorizeNicknamesMode.ALL          -> false
+              MessageSettings.ColorizeNicknamesMode.ALL_BUT_MINE -> it.self
+              MessageSettings.ColorizeNicknamesMode.NONE         -> true
             }
+            val senderColor = if (useSelfColor) selfColor else senderColors[senderColorIndex]
 
             fun formatNick(nick: CharSequence): CharSequence {
               val spannableString = SpannableString(nick)
@@ -135,11 +130,7 @@ class AutoCompleteHelper(
 
             it.copy(
               displayNick = formatNick(it.nick),
-              fallbackDrawable = TextDrawable.builder().beginConfig()
-                .textColor((colorBackground and 0xFFFFFF) or (0x8A shl 24)).useFont(Typeface.DEFAULT_BOLD).endConfig().let {
-                  if (messageSettings.squareAvatars) it.buildRoundRect(initial, senderColor, radius)
-                  else it.buildRound(initial, senderColor)
-                },
+              fallbackDrawable = colorContext.buildTextDrawable(initial, senderColor),
               modes = when (messageSettings.showPrefix) {
                 MessageSettings.ShowPrefixMode.ALL ->
                   it.modes
@@ -157,10 +148,7 @@ class AutoCompleteHelper(
             else colorAway
 
             it.copy(
-              icon = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT_BOLD).endConfig().let {
-                if (messageSettings.squareAvatars) it.buildRoundRect("#", color, radius)
-                else it.buildRound("#", color)
-              }
+              icon = colorContext.buildTextDrawable("#", color)
             )
           }
           else                            -> it
@@ -180,10 +168,6 @@ class AutoCompleteHelper(
     this.dataListeners += listener
   }
 
-  fun removeDataListener(listener: ((List<AutoCompleteItem>) -> Unit)) {
-    this.dataListeners -= listener
-  }
-
   private fun fullAutoComplete(sessionOptional: Optional<ISession>, id: Int,
                                lastWord: Pair<String, IntRange>): List<AutoCompleteItem> {
     val session = sessionOptional.orNull()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
index 7f1edb839e6e08975888cbae7f98d03557a32261..fd1d8853db932a6396e7b55ff6fd5a1dbcfe44a1 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
@@ -39,13 +39,13 @@ import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.persistence.QuasselDatabase
 import de.kuschku.quasseldroid.settings.MessageSettings
+import de.kuschku.quasseldroid.util.ColorContext
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
 import de.kuschku.quasseldroid.util.helper.styledAttributes
 import de.kuschku.quasseldroid.util.helper.visibleIf
 import de.kuschku.quasseldroid.util.irc.format.ContentFormatter
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
 import de.kuschku.quasseldroid.util.ui.SpanFormatter
-import de.kuschku.quasseldroid.util.ui.TextDrawable
 import de.kuschku.quasseldroid.viewmodel.data.FormattedMessage
 import org.threeten.bp.ZoneId
 import org.threeten.bp.format.DateTimeFormatter
@@ -98,11 +98,7 @@ class QuasselMessageRenderer @Inject constructor(
     getColor(0, 0)
   }
 
-  private val colorBackground = context.theme.styledAttributes(R.attr.colorBackground) {
-    getColor(0, 0)
-  }
-
-  private val radius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius)
+  private val colorContext = ColorContext(context, messageSettings)
 
   private val zoneId = ZoneId.systemDefault()
 
@@ -240,13 +236,13 @@ class QuasselMessageRenderer @Inject constructor(
         val rawInitial = nickName.trimStart('-', '_', '[', ']', '{', '}', '|', '`', '^', '.', '\\')
                            .firstOrNull() ?: nickName.firstOrNull()
         val initial = rawInitial?.toUpperCase().toString()
-        val senderColor = when (messageSettings.colorizeNicknames) {
-          MessageSettings.ColorizeNicknamesMode.ALL          -> senderColors[senderColorIndex]
+        val useSelfColor = when (messageSettings.colorizeNicknames) {
+          MessageSettings.ColorizeNicknamesMode.ALL          -> false
           MessageSettings.ColorizeNicknamesMode.ALL_BUT_MINE ->
-            if (message.content.flag.hasFlag(Message_Flag.Self)) selfColor
-            else senderColors[senderColorIndex]
-          MessageSettings.ColorizeNicknamesMode.NONE         -> selfColor
+            message.content.flag.hasFlag(Message_Flag.Self)
+          MessageSettings.ColorizeNicknamesMode.NONE         -> true
         }
+        val senderColor = if (useSelfColor) selfColor else senderColors[senderColorIndex]
 
         FormattedMessage(
           id = message.content.messageId,
@@ -261,11 +257,7 @@ class QuasselMessageRenderer @Inject constructor(
           },
           realName = realName,
           avatarUrls = AvatarHelper.avatar(messageSettings, message.content, avatarSize),
-          fallbackDrawable = TextDrawable.builder().beginConfig()
-            .textColor((colorBackground and 0xFFFFFF) or (0x8A shl 24)).useFont(Typeface.DEFAULT_BOLD).endConfig().let {
-              if (messageSettings.squareAvatars) it.buildRoundRect(initial, senderColor, radius)
-              else it.buildRound(initial, senderColor)
-            },
+          fallbackDrawable = colorContext.buildTextDrawable(initial, senderColor),
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
@@ -278,13 +270,13 @@ class QuasselMessageRenderer @Inject constructor(
         val rawInitial = nickName.trimStart('-', '_', '[', ']', '{', '}', '|', '`', '^', '.', '\\')
                            .firstOrNull() ?: nickName.firstOrNull()
         val initial = rawInitial?.toUpperCase().toString()
-        val senderColor = when (messageSettings.colorizeNicknames) {
-          MessageSettings.ColorizeNicknamesMode.ALL          -> senderColors[senderColorIndex]
+        val useSelfColor = when (messageSettings.colorizeNicknames) {
+          MessageSettings.ColorizeNicknamesMode.ALL          -> false
           MessageSettings.ColorizeNicknamesMode.ALL_BUT_MINE ->
-            if (message.content.flag.hasFlag(Message_Flag.Self)) selfColor
-            else senderColors[senderColorIndex]
-          MessageSettings.ColorizeNicknamesMode.NONE         -> selfColor
+            message.content.flag.hasFlag(Message_Flag.Self)
+          MessageSettings.ColorizeNicknamesMode.NONE         -> true
         }
+        val senderColor = if (useSelfColor) selfColor else senderColors[senderColorIndex]
 
         FormattedMessage(
           id = message.content.messageId,
@@ -297,11 +289,7 @@ class QuasselMessageRenderer @Inject constructor(
             contentFormatter.formatContent(message.content.content, monochromeForeground)
           ),
           avatarUrls = AvatarHelper.avatar(messageSettings, message.content, avatarSize),
-          fallbackDrawable = TextDrawable.builder().beginConfig()
-            .textColor((colorBackground and 0xFFFFFF) or (0x8A shl 24)).useFont(Typeface.DEFAULT_BOLD).endConfig().let {
-              if (messageSettings.squareAvatars) it.buildRoundRect(initial, senderColor, radius)
-              else it.buildRound(initial, senderColor)
-            },
+          fallbackDrawable = colorContext.buildTextDrawable(initial, senderColor),
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
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 ab6f3703de978513ec03f212d55d8c579b13d9db..d59244be1239b42900ee8405a08cdac11bc32a95 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
@@ -47,13 +47,13 @@ import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AppearanceSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.ui.chat.info.user.UserInfoActivity
+import de.kuschku.quasseldroid.util.ColorContext
 import de.kuschku.quasseldroid.util.avatars.AvatarHelper
 import de.kuschku.quasseldroid.util.helper.loadWithFallbacks
 import de.kuschku.quasseldroid.util.helper.styledAttributes
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer
 import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
-import de.kuschku.quasseldroid.util.ui.TextDrawable
 import de.kuschku.quasseldroid.viewmodel.EditorViewModel.Companion.IGNORED_CHARS
 import de.kuschku.quasseldroid.viewmodel.data.Avatar
 import javax.inject.Inject
@@ -98,11 +98,7 @@ class NickListFragment : ServiceBoundFragment() {
       getColor(0, 0)
     }
 
-    val colorBackground = requireContext().theme.styledAttributes(R.attr.colorBackground) {
-      getColor(0, 0)
-    }
-
-    val radius = requireContext().resources.getDimensionPixelSize(R.dimen.avatar_radius)
+    val colorContext = ColorContext(requireContext(), messageSettings)
 
     val avatarSize = resources.getDimensionPixelSize(R.dimen.avatar_size)
     viewModel.nickData.toLiveData().observe(this, Observer {
@@ -113,13 +109,12 @@ class NickListFragment : ServiceBoundFragment() {
           val rawInitial = nickName.trimStart(*IGNORED_CHARS)
                              .firstOrNull() ?: nickName.firstOrNull()
           val initial = rawInitial?.toUpperCase().toString()
-          val senderColor = when (messageSettings.colorizeNicknames) {
-            MessageSettings.ColorizeNicknamesMode.ALL          -> senderColors[senderColorIndex]
-            MessageSettings.ColorizeNicknamesMode.ALL_BUT_MINE ->
-              if (it.self) selfColor
-              else senderColors[senderColorIndex]
-            MessageSettings.ColorizeNicknamesMode.NONE         -> selfColor
+          val useSelfColor = when (messageSettings.colorizeNicknames) {
+            MessageSettings.ColorizeNicknamesMode.ALL          -> false
+            MessageSettings.ColorizeNicknamesMode.ALL_BUT_MINE -> it.self
+            MessageSettings.ColorizeNicknamesMode.NONE         -> true
           }
+          val senderColor = if (useSelfColor) selfColor else senderColors[senderColorIndex]
 
           fun formatNick(nick: CharSequence): CharSequence {
             val spannableString = SpannableString(nick)
@@ -139,11 +134,7 @@ class NickListFragment : ServiceBoundFragment() {
           }
           it.copy(
             displayNick = formatNick(it.nick),
-            fallbackDrawable = TextDrawable.builder().beginConfig()
-              .textColor((colorBackground and 0xFFFFFF) or (0x8A shl 24)).useFont(Typeface.DEFAULT_BOLD).endConfig().let {
-                if (messageSettings.squareAvatars) it.buildRoundRect(initial, senderColor, radius)
-                else it.buildRound(initial, senderColor)
-              },
+            fallbackDrawable = colorContext.buildTextDrawable(initial, senderColor),
             initial = initial,
             modes = when (messageSettings.showPrefix) {
               MessageSettings.ShowPrefixMode.ALL ->
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 2b30d7214c697187bd5f5cbe77f1808de7a597d9..7f70989c03a5e5c2c48acbc538787290a774667a 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
@@ -44,7 +44,6 @@ import de.kuschku.libquassel.util.helpers.nullIf
 import de.kuschku.quasseldroid.Keys
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AppearanceSettings
-import de.kuschku.quasseldroid.settings.ConnectionSettings
 import de.kuschku.quasseldroid.settings.Settings
 import de.kuschku.quasseldroid.ui.clientsettings.about.AboutActivity
 import de.kuschku.quasseldroid.ui.clientsettings.client.ClientSettingsActivity
@@ -98,9 +97,6 @@ abstract class ServiceBoundSetupActivity :
     }
   }
 
-  @Inject
-  lateinit var connectionSettings: ConnectionSettings
-
   @Inject
   lateinit var appearanceSettings: AppearanceSettings
 
@@ -109,8 +105,6 @@ abstract class ServiceBoundSetupActivity :
 
   protected var accountId: Long = -1
 
-  private var startedSelection = false
-
   class SetupActivityViewPagerPageChangeListener(private val activity: ServiceBoundSetupActivity) :
     ViewPager.OnPageChangeListener {
     override fun onPageScrollStateChanged(state: Int) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ValidityChangeCallback.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ValidityChangeCallback.kt
deleted file mode 100644
index 3969433296a39a7bfa71011b01758f7d6428fbe7..0000000000000000000000000000000000000000
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/ValidityChangeCallback.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2018 Janne Koschinski
- * Copyright (c) 2018 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.quasseldroid.ui.setup
-
-interface ValidityChangeCallback {
-  fun invoke(isValid: Boolean)
-}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountAdapter.kt
index d0e6741bafb7f05200f621fe475b4178f71bf92b..c72746b1efd1d00c2c3918875b46e460333f16d8 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/accounts/selection/AccountAdapter.kt
@@ -133,26 +133,14 @@ class AccountAdapter(
     actionListeners.add(f)
   }
 
-  fun removeEditListener(f: (Long) -> Unit) {
-    actionListeners.remove(f)
-  }
-
   fun addAddListener(f: () -> Unit) {
     addListeners.add(f)
   }
 
-  fun removeAddListener(f: () -> Unit) {
-    addListeners.remove(f)
-  }
-
   fun addSelectionListener(f: (Long) -> Unit) {
     selectionListeners.add(f)
   }
 
-  fun removeSelectionListener(f: (Long) -> Unit) {
-    selectionListeners.remove(f)
-  }
-
   override fun onBindViewHolder(holder: AccountViewHolder,
                                 @SuppressLint("RecyclerView") position: Int) {
     when (holder) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ColorContext.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ColorContext.kt
new file mode 100644
index 0000000000000000000000000000000000000000..37aedae6e47814efe8b532b37fb8a6c50de77b60
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ColorContext.kt
@@ -0,0 +1,61 @@
+package de.kuschku.quasseldroid.util
+
+import android.content.Context
+import android.graphics.Typeface
+import android.support.annotation.ColorInt
+import de.kuschku.libquassel.util.irc.SenderColorUtil
+import de.kuschku.quasseldroid.R
+import de.kuschku.quasseldroid.settings.MessageSettings
+import de.kuschku.quasseldroid.util.helper.styledAttributes
+import de.kuschku.quasseldroid.util.ui.TextDrawable
+import de.kuschku.quasseldroid.viewmodel.EditorViewModel
+
+class ColorContext(context: Context, private val messageSettings: MessageSettings) {
+  val senderColors = context.theme.styledAttributes(
+    R.attr.senderColor0, R.attr.senderColor1, R.attr.senderColor2, R.attr.senderColor3,
+    R.attr.senderColor4, R.attr.senderColor5, R.attr.senderColor6, R.attr.senderColor7,
+    R.attr.senderColor8, R.attr.senderColor9, R.attr.senderColorA, R.attr.senderColorB,
+    R.attr.senderColorC, R.attr.senderColorD, R.attr.senderColorE, R.attr.senderColorF
+  ) {
+    IntArray(length()) {
+      getColor(it, 0)
+    }
+  }
+
+  val selfColor = context.theme.styledAttributes(R.attr.colorForegroundSecondary) {
+    getColor(0, 0)
+  }
+
+  val textColor = context.theme.styledAttributes(R.attr.colorBackground) {
+    getColor(0, 0)
+  }
+
+  val radius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius)
+
+
+  fun prepareTextDrawable(@ColorInt textColor: Int = this.textColor) =
+    TextDrawable.builder()
+      .beginConfig()
+      .textColor(setAlpha(textColor, 0x8A))
+      .useFont(Typeface.DEFAULT_BOLD)
+      .endConfig()
+
+  fun buildTextDrawable(initial: String, @ColorInt backgroundColor: Int) =
+    prepareTextDrawable(textColor).let {
+      if (messageSettings.squareAvatars) it.buildRoundRect(initial, backgroundColor, radius)
+      else it.buildRound(initial, backgroundColor)
+    }
+
+  fun buildTextDrawable(nickName: String, self: Boolean): TextDrawable {
+    val senderColorIndex = SenderColorUtil.senderColor(nickName)
+    val rawInitial = nickName.trimStart(*EditorViewModel.IGNORED_CHARS).firstOrNull()
+                     ?: nickName.firstOrNull()
+    val initial = rawInitial?.toUpperCase().toString()
+    val senderColor = if (self) selfColor else senderColors[senderColorIndex]
+
+    return buildTextDrawable(initial, senderColor)
+  }
+
+  @ColorInt
+  private fun setAlpha(@ColorInt color: Int, alpha: Int) = (color and 0xFFFFFF) or (alpha shl 24)
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/helper/BooleanHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/helper/BooleanHelper.kt
index 1c4cebcf85ea2939d2b7096784939de5c6b018dc..78b45b58b658eb9b8835966516d9d8c60912b367 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/helper/BooleanHelper.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/helper/BooleanHelper.kt
@@ -22,7 +22,3 @@ package de.kuschku.quasseldroid.util.helper
 inline fun <R> Boolean.letIf(block: () -> R): R? {
   return if (this) block() else null
 }
-
-inline fun <R> Boolean.letUnless(block: () -> R): R? {
-  return if (this) null else block()
-}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/helper/CharSequenceHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/helper/CharSequenceHelper.kt
index 898e97dc8ca62b4ef57a389b4d5f40e123ac4c37..b4e11d26c09431fc152f811cc9c6e0b3d3ee66f3 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/helper/CharSequenceHelper.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/helper/CharSequenceHelper.kt
@@ -147,11 +147,6 @@ fun CharSequence.splitToSequence(vararg delimiters: String, ignoreCase: Boolean
 
 fun CharSequence.lineSequence(): Sequence<CharSequence> = splitToSequence("\r\n", "\n", "\r")
 
-fun CharSequence.lastWord(cursor: Int = this.length,
-                          onlyBeforeCursor: Boolean = false): CharSequence {
-  return lastWordIndices(cursor, onlyBeforeCursor)?.let { subSequence(it) } ?: ""
-}
-
 fun CharSequence.lastWordIndices(cursor: Int = this.length,
                                  onlyBeforeCursor: Boolean = false): IntRange? {
   val cursorPosition = if (cursor != -1) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/exceptions/DeserializationException.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/exceptions/DeserializationException.kt
deleted file mode 100644
index a5c6095ef61c37b3655e90d319f3f88a09cce314..0000000000000000000000000000000000000000
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/exceptions/DeserializationException.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2018 Janne Koschinski
- * Copyright (c) 2018 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.quassel.exceptions
-
-class DeserializationException : Exception {
-  constructor() : super()
-  constructor(p0: String?) : super(p0)
-  constructor(p0: String?, p1: Throwable?) : super(p0, p1)
-  constructor(p0: Throwable?) : super(p0)
-  constructor(p0: String?, p1: Throwable?, p2: Boolean, p3: Boolean) : super(p0, p1, p2, p3)
-}
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 d4e6721b11a09649c9d5bc9b75437702e2b5b6be..24ea3d1e2cbcd1762a8fd50510c5295fdb59f227 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt
@@ -97,14 +97,6 @@ class SessionManager(
     Invokers
   }
 
-  fun ifClosed(closure: (ISession) -> Unit) {
-    state.or(ConnectionState.DISCONNECTED).let {
-      if (it == ConnectionState.CLOSED) {
-        closure(inProgressSession.value)
-      }
-    }
-  }
-
   fun ifDisconnected(closure: (ISession) -> Unit) {
     state.or(ConnectionState.DISCONNECTED).let {
       if (it == ConnectionState.CLOSED || it == ConnectionState.DISCONNECTED) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt
index 51649718d774001339bd9823b5bde7b362c8cd1e..6e6f989552d6ffe1c9aa1e98f64845d9fe208fdc 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt
@@ -21,5 +21,3 @@ package de.kuschku.libquassel.util.helpers
 
 inline fun Int.clamp(lowerBound: Int, upperBound: Int): Int =
   maxOf(lowerBound, minOf(this, upperBound))
-
-inline fun Int.clamp(range: IntRange): Int = clamp(range.start, range.last)
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt
index 1bc49af7edce6a3c100c933fbaeada582b734ae6..5b8122bbce7ce33f987c9bfcba161c57f550ee3e 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/helpers/ObservableHelper.kt
@@ -62,15 +62,6 @@ fun <T : Any, U : Any> Observable<Optional<T>>.mapSwitchMap(
   }
 }
 
-fun <T : Any, U : Any> Observable<Optional<T>>.mapSwitchMapEmpty(
-  mapper: (T) -> Observable<U>): Observable<U> = switchMap {
-  if (it.isPresent()) {
-    it.map(mapper).get()
-  } else {
-    Observable.empty()
-  }
-}
-
 fun <T : Any, U : Any> Observable<Optional<T>>.flatMapSwitchMap(
   mapper: (T) -> Observable<Optional<U>>): Observable<Optional<U>> = switchMap {
   it.map(mapper).orElse(Observable.just(Optional.empty()))
diff --git a/lifecycle-ktx/build.gradle.kts b/lifecycle-ktx/build.gradle.kts
index 42b0627f20ed1cf1b927435d940b460ac43f85ce..e92236290d6e0355f041677e4ca857a31f3a3be8 100644
--- a/lifecycle-ktx/build.gradle.kts
+++ b/lifecycle-ktx/build.gradle.kts
@@ -20,12 +20,10 @@
 import org.gradle.api.Project
 import org.gradle.api.artifacts.ExternalModuleDependency
 import org.gradle.kotlin.dsl.*
-import org.jetbrains.kotlin.gradle.plugin.KaptExtension
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 plugins {
   kotlin("jvm")
-  kotlin("kapt")
 }
 
 dependencies {
diff --git a/malheur/build.gradle.kts b/malheur/build.gradle.kts
index 2482fd8467d16fe5ad11d92ccaedf8be540fe0f1..1928ceabbcf65f71f63ad70ba596a0a506704584 100644
--- a/malheur/build.gradle.kts
+++ b/malheur/build.gradle.kts
@@ -20,7 +20,6 @@
 plugins {
   id("com.android.library")
   kotlin("android")
-  kotlin("kapt")
 }
 
 android {
@@ -41,7 +40,7 @@ android {
 
   lintOptions {
     isWarningsAsErrors = true
-    setLintConfig(file("../lint.xml"))
+    lintConfig = file("../lint.xml")
   }
 }
 
diff --git a/persistence/build.gradle.kts b/persistence/build.gradle.kts
index 99cc28ef9457fd292eed31c492da4a0a3e04dbc2..b6b3587305e90c42ee821ce6bb798e08fad0f7cb 100644
--- a/persistence/build.gradle.kts
+++ b/persistence/build.gradle.kts
@@ -47,7 +47,7 @@ android {
 
   lintOptions {
     isWarningsAsErrors = true
-    setLintConfig(file("../lint.xml"))
+    lintConfig = file("../lint.xml")
   }
 }
 
diff --git a/viewmodel/build.gradle.kts b/viewmodel/build.gradle.kts
index 3267b9193c8e7245909beb2de275843d46d041c3..c99c4a3dbe62597ec0807f7e4a7d36247beb5520 100644
--- a/viewmodel/build.gradle.kts
+++ b/viewmodel/build.gradle.kts
@@ -20,7 +20,6 @@
 plugins {
   id("com.android.library")
   kotlin("android")
-  kotlin("kapt")
 }
 
 android {
@@ -41,7 +40,7 @@ android {
 
   lintOptions {
     isWarningsAsErrors = true
-    setLintConfig(file("../lint.xml"))
+    lintConfig = file("../lint.xml")
   }
 }
 
@@ -57,7 +56,6 @@ dependencies {
   withVersion("1.1.1") {
     implementation("android.arch.lifecycle", "extensions", version)
     implementation("android.arch.lifecycle", "reactivestreams", version)
-    kapt("android.arch.lifecycle", "compiler", version)
   }
 
   // Utility
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/LiveDataHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/LiveDataHelper.kt
index e35c9e8e8dc42ebfe71ebf98b9da679aa6d95c74..4d139a946fac7f871e172b6e092c22deecc50d1f 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/LiveDataHelper.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/LiveDataHelper.kt
@@ -103,11 +103,6 @@ inline fun <X, Y> LiveData<X?>.switchMapRx(
   return result
 }
 
-@MainThread
-inline fun <X, Y> LiveData<out X?>.switchMapRx(
-  crossinline func: (X) -> Observable<Y>?
-): LiveData<Y?> = switchMapRx(BackpressureStrategy.LATEST, func)
-
 @MainThread
 inline fun <X, Y> LiveData<out X?>.map(
   crossinline func: (X) -> Y?
@@ -119,19 +114,6 @@ inline fun <X, Y> LiveData<out X?>.map(
   return result
 }
 
-@MainThread
-inline fun <X> LiveData<X>.orElse(
-  crossinline func: () -> X
-): LiveData<X> {
-  val result = object : MediatorLiveData<X>() {
-    override fun getValue() = super.getValue() ?: func()
-  }
-  result.addSource(this) { x ->
-    result.value = x ?: func()
-  }
-  return result
-}
-
 @MainThread
 inline fun <X> LiveData<X?>.or(
   default: X