From b4e3f68c33221e1c56542650d07f99f1f87f5f87 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Mon, 11 Feb 2019 13:24:50 +0100
Subject: [PATCH] Only expand messages which have spoilers

---
 .../service/QuasselNotificationBackend.kt     |   2 +-
 .../ui/chat/messages/MessageListFragment.kt   |   2 +-
 .../chat/messages/QuasselMessageRenderer.kt   | 399 +++++++++++-------
 .../ui/info/channel/ChannelInfoFragment.kt    |   7 +-
 .../ui/info/channellist/ChannelListAdapter.kt |   6 +-
 .../ui/info/user/UserInfoFragment.kt          |   7 +-
 .../util/irc/format/ContentFormatter.kt       |  19 +-
 .../viewmodel/data/FormattedMessage.kt        |   3 +-
 8 files changed, 269 insertions(+), 176 deletions(-)

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 6818bdf08..13105edf5 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
@@ -352,7 +352,7 @@ class QuasselNotificationBackend @Inject constructor(
             selfColor = selfColor
           ))
         }
-        val content = contentFormatter.formatContent(it.content, false, false, it.networkId)
+        val (content, _) = contentFormatter.formatContent(it.content, false, false, it.networkId)
 
         NotificationMessage(
           messageId = it.messageId,
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 d129255f3..ed05bd91a 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
@@ -253,7 +253,7 @@ class MessageListFragment : ServiceBoundFragment() {
           1    -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true
           else -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
         }
-      } else {
+      } else if (msg.hasSpoilers) {
         val value = viewModel.expandedMessages.value
         viewModel.expandedMessages.onNext(
           if (value.contains(msg.original.messageId)) value - msg.original.messageId
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 c1a442171..e1dfd0eb8 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
@@ -257,10 +257,10 @@ class QuasselMessageRenderer @Inject constructor(
             false
           ))
         }
-        val content = contentFormatter.formatContent(message.content.content,
-                                                     monochromeForeground,
-                                                     message.isExpanded,
-                                                     message.content.networkId)
+        val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
+                                                                    monochromeForeground,
+                                                                    message.isExpanded,
+                                                                    message.content.networkId)
         val nickName = HostmaskHelper.nick(message.content.sender)
         val senderColorIndex = SenderColorUtil.senderColor(nickName)
         val rawInitial = nickName.trimStart(*EditorViewModel.IGNORED_CHARS)
@@ -291,7 +291,8 @@ class QuasselMessageRenderer @Inject constructor(
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
-          isSelected = message.isSelected
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
         )
       }
       Message_Type.Action       -> {
@@ -308,6 +309,11 @@ class QuasselMessageRenderer @Inject constructor(
         }
         val senderColor = if (useSelfColor) selfColor else senderColors[senderColorIndex]
 
+        val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
+                                                                    monochromeForeground,
+                                                                    message.isExpanded,
+                                                                    message.content.networkId)
+
         FormattedMessage(
           original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
@@ -316,37 +322,39 @@ class QuasselMessageRenderer @Inject constructor(
             context.getString(R.string.message_format_action),
             contentFormatter.formatPrefix(message.content.senderPrefixes),
             contentFormatter.formatNick(message.content.sender, self, monochromeForeground, false),
-            contentFormatter.formatContent(message.content.content,
-                                           monochromeForeground,
-                                           message.isExpanded,
-                                           message.content.networkId)
+            content
           ),
           avatarUrls = AvatarHelper.avatar(messageSettings, message.content, avatarSize),
           fallbackDrawable = colorContext.buildTextDrawable(initial, senderColor),
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
-          isSelected = message.isSelected
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
+        )
+      }
+      Message_Type.Notice       -> {
+        val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
+                                                                    monochromeForeground,
+                                                                    message.isExpanded,
+                                                                    message.content.networkId)
+        FormattedMessage(
+          original = message.content,
+          time = timeFormatter.format(message.content.time.atZone(zoneId)),
+          dayChange = formatDayChange(message),
+          combined = SpanFormatter.format(
+            context.getString(R.string.message_format_notice),
+            contentFormatter.formatPrefix(message.content.senderPrefixes),
+            contentFormatter.formatNick(message.content.sender, self, monochromeForeground, false),
+            content
+          ),
+          hasDayChange = message.hasDayChange,
+          isMarkerLine = message.isMarkerLine,
+          isExpanded = message.isExpanded,
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
         )
       }
-      Message_Type.Notice       -> FormattedMessage(
-        original = message.content,
-        time = timeFormatter.format(message.content.time.atZone(zoneId)),
-        dayChange = formatDayChange(message),
-        combined = SpanFormatter.format(
-          context.getString(R.string.message_format_notice),
-          contentFormatter.formatPrefix(message.content.senderPrefixes),
-          contentFormatter.formatNick(message.content.sender, self, monochromeForeground, false),
-          contentFormatter.formatContent(message.content.content,
-                                         monochromeForeground,
-                                         message.isExpanded,
-                                         message.content.networkId)
-        ),
-        hasDayChange = message.hasDayChange,
-        isMarkerLine = message.isMarkerLine,
-        isExpanded = message.isExpanded,
-        isSelected = message.isSelected
-      )
       Message_Type.Nick         -> {
         val nickSelf = message.content.sender == message.content.content || self
         FormattedMessage(
@@ -386,7 +394,8 @@ class QuasselMessageRenderer @Inject constructor(
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
-          isSelected = message.isSelected
+          isSelected = message.isSelected,
+          hasSpoilers = false
         )
       }
       Message_Type.Mode         -> FormattedMessage(
@@ -402,7 +411,8 @@ class QuasselMessageRenderer @Inject constructor(
         hasDayChange = message.hasDayChange,
         isMarkerLine = message.isMarkerLine,
         isExpanded = message.isExpanded,
-        isSelected = message.isSelected
+        isSelected = message.isSelected,
+        hasSpoilers = false
       )
       Message_Type.Join         -> FormattedMessage(
         original = message.content,
@@ -422,87 +432,109 @@ class QuasselMessageRenderer @Inject constructor(
         hasDayChange = message.hasDayChange,
         isMarkerLine = message.isMarkerLine,
         isExpanded = message.isExpanded,
-        isSelected = message.isSelected
+        isSelected = message.isSelected,
+        hasSpoilers = false
       )
-      Message_Type.Part         -> FormattedMessage(
-        original = message.content,
-        time = timeFormatter.format(message.content.time.atZone(zoneId)),
-        dayChange = formatDayChange(message),
-        combined = if (message.content.content.isBlank()) {
-          SpanFormatter.format(
-            context.getString(R.string.message_format_part_1),
-            contentFormatter.formatPrefix(message.content.senderPrefixes),
-            contentFormatter.formatNick(
-              message.content.sender,
-              self,
-              monochromeForeground,
-              messageSettings.showHostmaskActions
-            )
+      Message_Type.Part         -> {
+        val (content, hasSpoilers) = if (message.content.content.isBlank()) {
+          Pair(
+            SpanFormatter.format(
+              context.getString(R.string.message_format_part_1),
+              contentFormatter.formatPrefix(message.content.senderPrefixes),
+              contentFormatter.formatNick(
+                message.content.sender,
+                self,
+                monochromeForeground,
+                messageSettings.showHostmaskActions
+              )
+            ),
+            false
           )
         } else {
-          SpanFormatter.format(
-            context.getString(R.string.message_format_part_2),
-            contentFormatter.formatPrefix(message.content.senderPrefixes),
-            contentFormatter.formatNick(
-              message.content.sender,
-              self,
-              monochromeForeground,
-              messageSettings.showHostmaskActions
+          val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
+                                                                      monochromeForeground,
+                                                                      message.isExpanded,
+                                                                      message.content.networkId)
+          Pair(
+            SpanFormatter.format(
+              context.getString(R.string.message_format_part_2),
+              contentFormatter.formatPrefix(message.content.senderPrefixes),
+              contentFormatter.formatNick(
+                message.content.sender,
+                self,
+                monochromeForeground,
+                messageSettings.showHostmaskActions
+              ),
+              content
             ),
-            contentFormatter.formatContent(message.content.content,
-                                           monochromeForeground,
-                                           message.isExpanded,
-                                           message.content.networkId)
+            hasSpoilers
           )
-        },
-        hasDayChange = message.hasDayChange,
-        isMarkerLine = message.isMarkerLine,
-        isExpanded = message.isExpanded,
-        isSelected = message.isSelected
-      )
-      Message_Type.Quit         -> FormattedMessage(
-        original = message.content,
-        time = timeFormatter.format(message.content.time.atZone(zoneId)),
-        dayChange = formatDayChange(message),
-        combined = if (message.content.content.isBlank()) {
-          SpanFormatter.format(
-            context.getString(R.string.message_format_quit_1),
-            contentFormatter.formatPrefix(message.content.senderPrefixes),
-            contentFormatter.formatNick(
-              message.content.sender,
-              self,
-              monochromeForeground,
-              messageSettings.showHostmaskActions
-            )
+        }
+
+        FormattedMessage(
+          original = message.content,
+          time = timeFormatter.format(message.content.time.atZone(zoneId)),
+          dayChange = formatDayChange(message),
+          combined = content,
+          hasDayChange = message.hasDayChange,
+          isMarkerLine = message.isMarkerLine,
+          isExpanded = message.isExpanded,
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
+        )
+      }
+      Message_Type.Quit         -> {
+        val (content, hasSpoilers) = if (message.content.content.isBlank()) {
+          Pair(
+            SpanFormatter.format(
+              context.getString(R.string.message_format_quit_1),
+              contentFormatter.formatPrefix(message.content.senderPrefixes),
+              contentFormatter.formatNick(
+                message.content.sender,
+                self,
+                monochromeForeground,
+                messageSettings.showHostmaskActions
+              )
+            ),
+            false
           )
         } else {
-          SpanFormatter.format(
-            context.getString(R.string.message_format_quit_2),
-            contentFormatter.formatPrefix(message.content.senderPrefixes),
-            contentFormatter.formatNick(
-              message.content.sender,
-              self,
-              monochromeForeground,
-              messageSettings.showHostmaskActions
+          val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
+                                                                      monochromeForeground,
+                                                                      message.isExpanded,
+                                                                      message.content.networkId)
+          Pair(
+            SpanFormatter.format(
+              context.getString(R.string.message_format_quit_2),
+              contentFormatter.formatPrefix(message.content.senderPrefixes),
+              contentFormatter.formatNick(
+                message.content.sender,
+                self,
+                monochromeForeground,
+                messageSettings.showHostmaskActions
+              ),
+              content
             ),
-            contentFormatter.formatContent(message.content.content,
-                                           monochromeForeground,
-                                           message.isExpanded,
-                                           message.content.networkId)
+            hasSpoilers
           )
-        },
-        hasDayChange = message.hasDayChange,
-        isMarkerLine = message.isMarkerLine,
-        isExpanded = message.isExpanded,
-        isSelected = message.isSelected
-      )
-      Message_Type.Kick         -> {
-        val (user, reason) = message.content.content.split(' ', limit = 2) + listOf("", "")
+        }
+
         FormattedMessage(
           original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
           dayChange = formatDayChange(message),
-          combined = if (reason.isBlank()) {
+          combined = content,
+          hasDayChange = message.hasDayChange,
+          isMarkerLine = message.isMarkerLine,
+          isExpanded = message.isExpanded,
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
+        )
+      }
+      Message_Type.Kick         -> {
+        val (user, reason) = message.content.content.split(' ', limit = 2) + listOf("", "")
+        val (content, hasSpoilers) = if (reason.isBlank()) {
+          Pair(
             SpanFormatter.format(
               context.getString(R.string.message_format_kick_1),
               contentFormatter.formatNick(user, false, monochromeForeground, false),
@@ -511,8 +543,15 @@ class QuasselMessageRenderer @Inject constructor(
                                           self,
                                           monochromeForeground,
                                           false)
-            )
-          } else {
+            ),
+            false
+          )
+        } else {
+          val (content, hasSpoilers) = contentFormatter.formatContent(reason,
+                                                                      monochromeForeground,
+                                                                      message.isExpanded,
+                                                                      message.content.networkId)
+          Pair(
             SpanFormatter.format(
               context.getString(R.string.message_format_kick_2),
               contentFormatter.formatNick(user, false, monochromeForeground, false),
@@ -521,25 +560,28 @@ class QuasselMessageRenderer @Inject constructor(
                                           self,
                                           monochromeForeground,
                                           false),
-              contentFormatter.formatContent(reason,
-                                             monochromeForeground,
-                                             message.isExpanded,
-                                             message.content.networkId)
-            )
-          },
+              content
+            ),
+            hasSpoilers
+          )
+        }
+
+        FormattedMessage(
+          original = message.content,
+          time = timeFormatter.format(message.content.time.atZone(zoneId)),
+          dayChange = formatDayChange(message),
+          combined = content,
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
-          isSelected = message.isSelected
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
         )
       }
       Message_Type.Kill         -> {
         val (user, reason) = message.content.content.split(' ', limit = 2) + listOf("", "")
-        FormattedMessage(
-          original = message.content,
-          time = timeFormatter.format(message.content.time.atZone(zoneId)),
-          dayChange = formatDayChange(message),
-          combined = if (reason.isBlank()) {
+        val (content, hasSpoilers) = if (reason.isBlank()) {
+          Pair(
             SpanFormatter.format(
               context.getString(R.string.message_format_kill_1),
               contentFormatter.formatNick(user, false, monochromeForeground, false),
@@ -548,8 +590,15 @@ class QuasselMessageRenderer @Inject constructor(
                                           self,
                                           monochromeForeground,
                                           false)
-            )
-          } else {
+            ),
+            false
+          )
+        } else {
+          val (content, hasSpoilers) = contentFormatter.formatContent(reason,
+                                                                      monochromeForeground,
+                                                                      message.isExpanded,
+                                                                      message.content.networkId)
+          Pair(
             SpanFormatter.format(
               context.getString(R.string.message_format_kill_2),
               contentFormatter.formatNick(user, false, monochromeForeground, false),
@@ -558,16 +607,22 @@ class QuasselMessageRenderer @Inject constructor(
                                           self,
                                           monochromeForeground,
                                           false),
-              contentFormatter.formatContent(reason,
-                                             monochromeForeground,
-                                             message.isExpanded,
-                                             message.content.networkId)
-            )
-          },
+              content
+            ),
+            hasSpoilers
+          )
+        }
+
+        FormattedMessage(
+          original = message.content,
+          time = timeFormatter.format(message.content.time.atZone(zoneId)),
+          dayChange = formatDayChange(message),
+          combined = content,
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
-          isSelected = message.isSelected
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
         )
       }
       Message_Type.NetsplitJoin -> {
@@ -593,7 +648,8 @@ class QuasselMessageRenderer @Inject constructor(
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
-          isSelected = message.isSelected
+          isSelected = message.isSelected,
+          hasSpoilers = false
         )
       }
       Message_Type.NetsplitQuit -> {
@@ -619,37 +675,46 @@ class QuasselMessageRenderer @Inject constructor(
           hasDayChange = message.hasDayChange,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
-          isSelected = message.isSelected
+          isSelected = message.isSelected,
+          hasSpoilers = false
         )
       }
       Message_Type.Server,
       Message_Type.Info,
-      Message_Type.Error        -> FormattedMessage(
-        original = message.content,
-        time = timeFormatter.format(message.content.time.atZone(zoneId)),
-        dayChange = formatDayChange(message),
-        combined = contentFormatter.formatContent(message.content.content,
-                                                  monochromeForeground,
-                                                  message.isExpanded,
-                                                  message.content.networkId),
-        hasDayChange = message.hasDayChange,
-        isMarkerLine = message.isMarkerLine,
-        isExpanded = message.isExpanded,
-        isSelected = message.isSelected
-      )
-      Message_Type.Topic        -> FormattedMessage(
-        original = message.content,
-        time = timeFormatter.format(message.content.time.atZone(zoneId)),
-        dayChange = formatDayChange(message),
-        combined = contentFormatter.formatContent(message.content.content,
-                                                  monochromeForeground,
-                                                  message.isExpanded,
-                                                  message.content.networkId),
-        hasDayChange = message.hasDayChange,
-        isMarkerLine = message.isMarkerLine,
-        isExpanded = message.isExpanded,
-        isSelected = message.isSelected
-      )
+      Message_Type.Error        -> {
+        val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
+                                                                    monochromeForeground,
+                                                                    message.isExpanded,
+                                                                    message.content.networkId)
+        FormattedMessage(
+          original = message.content,
+          time = timeFormatter.format(message.content.time.atZone(zoneId)),
+          dayChange = formatDayChange(message),
+          combined = content,
+          hasDayChange = message.hasDayChange,
+          isMarkerLine = message.isMarkerLine,
+          isExpanded = message.isExpanded,
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
+        )
+      }
+      Message_Type.Topic        -> {
+        val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
+                                                                    monochromeForeground,
+                                                                    message.isExpanded,
+                                                                    message.content.networkId)
+        FormattedMessage(
+          original = message.content,
+          time = timeFormatter.format(message.content.time.atZone(zoneId)),
+          dayChange = formatDayChange(message),
+          combined = content,
+          hasDayChange = message.hasDayChange,
+          isMarkerLine = message.isMarkerLine,
+          isExpanded = message.isExpanded,
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
+        )
+      }
       Message_Type.DayChange    -> FormattedMessage(
         original = message.content,
         time = "",
@@ -658,21 +723,26 @@ class QuasselMessageRenderer @Inject constructor(
         hasDayChange = message.hasDayChange,
         isMarkerLine = false,
         isExpanded = false,
-        isSelected = false
-      )
-      Message_Type.Invite       -> FormattedMessage(
-        original = message.content,
-        time = timeFormatter.format(message.content.time.atZone(zoneId)),
-        dayChange = formatDayChange(message),
-        combined = contentFormatter.formatContent(message.content.content,
-                                                  monochromeForeground,
-                                                  message.isExpanded,
-                                                  message.content.networkId),
-        hasDayChange = message.hasDayChange,
-        isMarkerLine = message.isMarkerLine,
-        isExpanded = message.isExpanded,
-        isSelected = message.isSelected
+        isSelected = false,
+        hasSpoilers = false
       )
+      Message_Type.Invite       -> {
+        val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
+                                                                    monochromeForeground,
+                                                                    message.isExpanded,
+                                                                    message.content.networkId)
+        FormattedMessage(
+          original = message.content,
+          time = timeFormatter.format(message.content.time.atZone(zoneId)),
+          dayChange = formatDayChange(message),
+          combined = content,
+          hasDayChange = message.hasDayChange,
+          isMarkerLine = message.isMarkerLine,
+          isExpanded = message.isExpanded,
+          isSelected = message.isSelected,
+          hasSpoilers = hasSpoilers
+        )
+      }
       else                      -> FormattedMessage(
         original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
@@ -692,7 +762,8 @@ class QuasselMessageRenderer @Inject constructor(
         hasDayChange = message.hasDayChange,
         isMarkerLine = message.isMarkerLine,
         isExpanded = message.isExpanded,
-        isSelected = message.isSelected
+        isSelected = message.isSelected,
+        hasSpoilers = false
       )
     }
   }
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 2cf728b74..9126ee12c 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
@@ -109,8 +109,11 @@ class ChannelInfoFragment : ServiceBoundFragment() {
       }
     }.toLiveData().observe(this, Observer { (info, channel) ->
       name.text = channel.name()
-      topic.text = contentFormatter.formatContent(channel.topic(),
-                                                  networkId = channel.network().networkId())
+      val (content, hasSpoilers) = contentFormatter.formatContent(
+        channel.topic(),
+        networkId = channel.network().networkId()
+      )
+      topic.text = content
 
       currentBufferInfo = info
       actionShortcut.visibleIf(info != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/channellist/ChannelListAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/channellist/ChannelListAdapter.kt
index 3e96dc703..c4a90f205 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/channellist/ChannelListAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/channellist/ChannelListAdapter.kt
@@ -108,7 +108,11 @@ class ChannelListAdapter @Inject constructor(
 
     fun bind(data: IrcListHelper.ChannelDescription) {
       name.text = data.channelName
-      topic.text = contentFormatter.formatContent(data.topic, networkId = data.netId)
+      val (content, hasSpoilers) = contentFormatter.formatContent(
+        data.topic,
+        networkId = data.netId
+      )
+      topic.text = content
       users.text = itemView.context.resources.getQuantityString(R.plurals.label_user_count,
                                                                 data.userCount.toInt(),
                                                                 data.userCount.toInt())
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 fea4dba07..66ce0b3ee 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
@@ -225,8 +225,11 @@ class UserInfoFragment : ServiceBoundFragment() {
         }
 
         nick.text = user.nick
-        realName.text = contentFormatter.formatContent(user.realName ?: "",
-                                                       networkId = user.networkId)
+        val (content, hasSpoilers) = contentFormatter.formatContent(
+          user.realName ?: "",
+          networkId = user.networkId
+        )
+        realName.text = content
         realName.visibleIf(!user.realName.isNullOrBlank() && user.realName != user.nick)
 
         awayMessage.text = user.awayMessage.nullIf { it.isNullOrBlank() } ?: SpannableString(
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/irc/format/ContentFormatter.kt b/app/src/main/java/de/kuschku/quasseldroid/util/irc/format/ContentFormatter.kt
index 2ba3631dc..d4ead0e21 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/irc/format/ContentFormatter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/irc/format/ContentFormatter.kt
@@ -79,8 +79,8 @@ class ContentFormatter @Inject constructor(
 
   fun formatContent(content: String,
                     highlight: Boolean = false,
-                    showSpoilers: Boolean = false,
-                    networkId: NetworkId?): CharSequence {
+                    unhideSpoilers: Boolean = false,
+                    networkId: NetworkId?): Pair<CharSequence, Boolean> {
     val spans = mutableListOf<FormatInfo>()
     val formattedText = SpannableString(
       ircFormatDeserializer.formatString(
@@ -90,7 +90,7 @@ class ContentFormatter @Inject constructor(
       )
     )
 
-    if (showSpoilers) {
+    val hasSpoilers = if (unhideSpoilers) {
       spans.removeAll {
         when {
           it.format is IrcFormat.Color ->
@@ -101,6 +101,17 @@ class ContentFormatter @Inject constructor(
             false
         }
       }
+    } else {
+      spans.any {
+        when {
+          it.format is IrcFormat.Color ->
+            it.format.foreground == it.format.background
+          it.format is IrcFormat.Hex   ->
+            it.format.foreground == it.format.background
+          else                         ->
+            false
+        }
+      }
     }
 
     for (result in urlPattern.findAll(formattedText)) {
@@ -131,7 +142,7 @@ class ContentFormatter @Inject constructor(
       span.apply(formattedText)
     }
 
-    return formattedText
+    return Pair(formattedText, hasSpoilers)
   }
 
   private fun formatNickNickImpl(nick: String, self: Boolean, colorize: Boolean,
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt
index b946cbc38..106fd6e16 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/data/FormattedMessage.kt
@@ -36,7 +36,8 @@ class FormattedMessage(
   val hasDayChange: Boolean,
   val isSelected: Boolean,
   val isExpanded: Boolean,
-  val isMarkerLine: Boolean
+  val isMarkerLine: Boolean,
+  val hasSpoilers: Boolean
 ) {
   override fun equals(other: Any?): Boolean {
     if (this === other) return true
-- 
GitLab