From fc192610550d5eb36b5aa5f9d3a46c8250c6d4a7 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Thu, 7 Jun 2018 17:39:58 +0200
Subject: [PATCH] Cleanup

---
 app/build.gradle.kts                          |  2 +-
 .../quasseldroid/service/QuasselService.kt    |  4 --
 .../quasseldroid/ui/chat/ChatActivity.kt      | 14 +----
 .../chat/buffers/BufferViewConfigFragment.kt  | 58 +++---------------
 .../ui/chat/input/AutoCompleteHelper.kt       | 34 +++--------
 .../chat/messages/QuasselMessageRenderer.kt   | 40 +++++-------
 .../ui/chat/nicks/NickListFragment.kt         | 25 +++-----
 .../ui/setup/ServiceBoundSetupActivity.kt     |  6 --
 .../ui/setup/ValidityChangeCallback.kt        | 24 --------
 .../accounts/selection/AccountAdapter.kt      | 12 ----
 .../kuschku/quasseldroid/util/ColorContext.kt | 61 +++++++++++++++++++
 .../quasseldroid/util/helper/BooleanHelper.kt |  4 --
 .../util/helper/CharSequenceHelper.kt         |  5 --
 .../exceptions/DeserializationException.kt    | 28 ---------
 .../libquassel/session/SessionManager.kt      |  8 ---
 .../libquassel/util/helpers/MathHelper.kt     |  2 -
 .../util/helpers/ObservableHelper.kt          |  9 ---
 lifecycle-ktx/build.gradle.kts                |  2 -
 malheur/build.gradle.kts                      |  3 +-
 persistence/build.gradle.kts                  |  2 +-
 viewmodel/build.gradle.kts                    |  4 +-
 .../util/helper/LiveDataHelper.kt             | 18 ------
 22 files changed, 108 insertions(+), 257 deletions(-)
 delete mode 100644 app/src/main/java/de/kuschku/quasseldroid/ui/setup/ValidityChangeCallback.kt
 create mode 100644 app/src/main/java/de/kuschku/quasseldroid/util/ColorContext.kt
 delete mode 100644 lib/src/main/java/de/kuschku/libquassel/quassel/exceptions/DeserializationException.kt

diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index bbdc960c5..56d1cf866 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 7d5ccb03b..13bcc255c 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 9a7ef3470..8f4e1e819 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 dc7649ad2..513990d25 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 9f6cd378e..7414e030d 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 7f1edb839..fd1d8853d 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 ab6f3703d..d59244be1 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 2b30d7214..7f70989c0 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 396943329..000000000
--- 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 d0e6741ba..c72746b1e 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 000000000..37aedae6e
--- /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 1c4cebcf8..78b45b58b 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 898e97dc8..b4e11d26c 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 a5c6095ef..000000000
--- 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 d4e6721b1..24ea3d1e2 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 51649718d..6e6f98955 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 1bc49af7e..5b8122bbc 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 42b0627f2..e92236290 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 2482fd846..1928ceabb 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 99cc28ef9..b6b358730 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 3267b9193..c99c4a3db 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 e35c9e8e8..4d139a946 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
-- 
GitLab