From 694a3cfb60309692b5fe4fc6329965c63529cd41 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Fri, 30 Mar 2018 21:59:02 +0200
Subject: [PATCH] Hide avatar and nick if the same user is sending consecutive
 messages

---
 .../ui/chat/messages/MessageAdapter.kt        | 42 ++++++++++++-------
 .../ui/chat/messages/MessageRenderer.kt       |  5 ++-
 .../chat/messages/QuasselMessageRenderer.kt   | 14 ++++---
 .../res/layout/widget_chatmessage_plain.xml   |  1 +
 app/src/main/res/xml/preferences.xml          |  5 ++-
 .../persistence/QuasselDatabase.kt            | 25 ++++++-----
 .../viewmodel/data/FormattedMessage.kt        |  1 -
 7 files changed, 56 insertions(+), 37 deletions(-)

diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
index c223b4ede..2a4310464 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageAdapter.kt
@@ -59,31 +59,42 @@ class MessageAdapter(
   }
 
   override fun getItemViewType(position: Int) = getItem(position)?.let {
-    viewType(Message_Flags.of(it.content.type), Message_Flags.of(it.content.flag))
+    viewType(Message_Flags.of(it.content.type),
+             Message_Flags.of(it.content.flag),
+             it.content.followUp)
   } ?: 0
 
-  private fun viewType(type: Message_Types, flags: Message_Flags) =
-    if (flags.hasFlag(Message_Flag.Highlight)) {
-      -type.value
-    } else {
-      type.value
-    }
+  private fun viewType(type: Message_Types, flags: Message_Flags, followUp: Boolean) =
+    type.value or
+      (if (flags.hasFlag(Message_Flag.Highlight)) MASK_HIGHLIGHT else 0x00) or
+      (if (followUp) MASK_FOLLOWUP else 0x00)
 
   override fun getItemId(position: Int): Long {
     return getItem(position)?.content?.messageId?.toLong() ?: 0L
   }
 
   private fun messageType(viewType: Int): Message_Type? =
-    Message_Type.of(Math.abs(viewType)).enabledValues().firstOrNull()
+    Message_Type.of(viewType and MASK_TYPE).enabledValues().firstOrNull()
+
+  private fun hasHiglight(viewType: Int) = viewType and MASK_HIGHLIGHT != 0
 
-  private fun hasHiglight(viewType: Int) = viewType < 0
+  private fun isFollowUp(viewType: Int) = viewType and MASK_FOLLOWUP != 0
+
+  companion object {
+    const val SHIFT_HIGHLIGHT = 32 - 1
+    const val SHIFT_FOLLOWUP = SHIFT_HIGHLIGHT - 1
+    const val MASK_HIGHLIGHT = 0x01 shl SHIFT_HIGHLIGHT
+    const val MASK_FOLLOWUP = 0x01 shl SHIFT_FOLLOWUP
+    const val MASK_TYPE = 0xFFFF
+  }
 
   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuasselMessageViewHolder {
     val messageType = messageType(viewType)
     val hasHighlight = hasHiglight(viewType)
+    val isFollowUp = isFollowUp(viewType)
     val viewHolder = QuasselMessageViewHolder(
       LayoutInflater.from(parent.context).inflate(
-        messageRenderer.layout(messageType, hasHighlight),
+        messageRenderer.layout(messageType, hasHighlight, isFollowUp),
         parent,
         false
       ),
@@ -91,7 +102,7 @@ class MessageAdapter(
       selectionListener,
       expansionListener
     )
-    messageRenderer.init(viewHolder, messageType, hasHighlight)
+    messageRenderer.init(viewHolder, messageType, hasHighlight, isFollowUp)
     return viewHolder
   }
 
@@ -119,6 +130,10 @@ class MessageAdapter(
     @JvmField
     var avatar: ImageView? = null
 
+    @BindView(R.id.avatar_container)
+    @JvmField
+    var avatarContainer: View? = null
+
     @BindView(R.id.avatar_placeholder)
     @JvmField
     var avatarPlaceholder: Space? = null
@@ -184,11 +199,6 @@ class MessageAdapter(
 
       this.itemView.isSelected = message.isSelected
 
-      if (message.isFollowUp) {
-        name?.visibility = View.GONE
-        avatar?.visibility = View.GONE
-      }
-
       avatar?.let { avatarView ->
         GlideApp.with(itemView)
           .load(message.avatarUrl)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt
index 5ebf18cea..185bc59e2 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageRenderer.kt
@@ -8,7 +8,7 @@ import de.kuschku.quasseldroid.viewmodel.data.FormattedMessage
 
 interface MessageRenderer {
   @LayoutRes
-  fun layout(type: Message_Type?, hasHighlight: Boolean): Int
+  fun layout(type: Message_Type?, hasHighlight: Boolean, isFollowUp: Boolean): Int
 
   fun bind(holder: MessageAdapter.QuasselMessageViewHolder, message: FormattedMessage,
            original: QuasselDatabase.DatabaseMessage)
@@ -17,7 +17,8 @@ interface MessageRenderer {
 
   fun init(viewHolder: MessageAdapter.QuasselMessageViewHolder,
            messageType: Message_Type?,
-           hasHighlight: Boolean) {
+           hasHighlight: Boolean,
+           isFollowUp: Boolean) {
   }
 }
 
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 ce748f883..105c4ed2b 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
@@ -56,7 +56,8 @@ class QuasselMessageRenderer @Inject constructor(
 
   private val zoneId = ZoneId.systemDefault()
 
-  override fun layout(type: Message_Type?, hasHighlight: Boolean) = when (type) {
+  override fun layout(type: Message_Type?, hasHighlight: Boolean,
+                      isFollowUp: Boolean) = when (type) {
     Notice    -> R.layout.widget_chatmessage_notice
     Server    -> R.layout.widget_chatmessage_server
     Error     -> R.layout.widget_chatmessage_error
@@ -70,7 +71,8 @@ class QuasselMessageRenderer @Inject constructor(
 
   override fun init(viewHolder: MessageAdapter.QuasselMessageViewHolder,
                     messageType: Message_Type?,
-                    hasHighlight: Boolean) {
+                    hasHighlight: Boolean,
+                    isFollowUp: Boolean) {
     if (hasHighlight) {
       viewHolder.itemView.context.theme.styledAttributes(
         R.attr.colorForegroundHighlight, R.attr.colorBackgroundHighlight,
@@ -95,10 +97,11 @@ class QuasselMessageRenderer @Inject constructor(
       viewHolder.combined?.typeface = if (viewHolder.combined?.typeface?.isItalic == true) monospaceItalic else Typeface.MONOSPACE
     }
 
-    viewHolder.avatar?.visibleIf(messageSettings.showAvatars || true)
-    viewHolder.avatarPlaceholder?.visibleIf(messageSettings.showAvatars || true)
+    viewHolder.avatar?.visibleIf(!isFollowUp)
+    viewHolder.avatarContainer?.visibleIf(messageSettings.showAvatars)
+    viewHolder.avatarPlaceholder?.visibleIf(messageSettings.showAvatars)
     val separateLine = viewHolder.content != null && viewHolder.name != null && messageSettings.nicksOnNewLine
-    viewHolder.name?.visibleIf(separateLine)
+    viewHolder.name?.visibleIf(separateLine && !isFollowUp)
     viewHolder.content?.visibleIf(separateLine)
     viewHolder.combined?.visibleIf(!separateLine)
 
@@ -161,7 +164,6 @@ class QuasselMessageRenderer @Inject constructor(
           combined = SpanFormatter.format("%s: %s", nick, content),
           avatarUrl = message.avatarUrl,
           fallbackDrawable = TextDrawable.builder().buildRound(initial, senderColor),
-          isFollowUp = message.content.followUp,
           isMarkerLine = message.isMarkerLine,
           isExpanded = message.isExpanded,
           isSelected = message.isSelected
diff --git a/app/src/main/res/layout/widget_chatmessage_plain.xml b/app/src/main/res/layout/widget_chatmessage_plain.xml
index 946c39fc1..f0761655b 100644
--- a/app/src/main/res/layout/widget_chatmessage_plain.xml
+++ b/app/src/main/res/layout/widget_chatmessage_plain.xml
@@ -30,6 +30,7 @@
       tools:text="@sample/messages.json/data/time" />
 
     <FrameLayout
+      android:id="@+id/avatar_container"
       android:layout_width="@dimen/avatar_size"
       android:layout_height="wrap_content"
       android:layout_marginBottom="@dimen/message_vertical"
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 1d67cdc48..9193f53bf 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -69,8 +69,9 @@
 
     <SwitchPreference
       android:defaultValue="false"
-      android:dependency="@string/preference_nicks_on_new_line_summary"
-      android:key="@string/preference_show_avatars_key" />
+      android:dependency="@string/preference_nicks_on_new_line_key"
+      android:key="@string/preference_show_avatars_key"
+      android:title="@string/preference_show_avatars_title" />
 
     <SwitchPreference
       android:defaultValue="false"
diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
index 40b3984eb..df1f595d5 100644
--- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
+++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt
@@ -212,16 +212,21 @@ FROM
       sender,
       senderPrefixes,
       content,
-      sender = coalesce((SELECT sender
-                         FROM message m
-                         WHERE m.messageId < message.messageId
-                               AND bufferId = ?
-                               AND type & ~? > 0
-                               AND date(datetime(m.time / 1000, 'unixepoch', 'localtime')) =
-                                   date(datetime(message.time / 1000, 'unixepoch', 'localtime'))
-                         ORDER BY m.messageId
-                           DESC
-                         LIMIT 1), 0) AS followUp
+      (SELECT 1
+       FROM
+         (SELECT *
+          FROM message m
+          WHERE m.messageId < message.messageId
+                AND bufferId = ?
+                AND type & ~? > 0
+          ORDER BY m.messageId
+            DESC
+          LIMIT 1) t
+       WHERE t.sender = message.sender
+             AND strftime('%s', date(datetime(t.time / 1000, 'unixepoch', 'localtime')), 'utc') * 1000 =
+                 strftime('%s', date(datetime(message.time / 1000, 'unixepoch', 'localtime')), 'utc') * 1000
+             AND t.type = message.type
+      ) = 1 AS followUp
     FROM message
     WHERE bufferId = ?
           AND type & ~? > 0
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 2ae1319a6..fd7c7865b 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
@@ -10,7 +10,6 @@ class FormattedMessage(
   val combined: CharSequence,
   val fallbackDrawable: Drawable? = null,
   val avatarUrl: String? = null,
-  val isFollowUp: Boolean = false,
   val isSelected: Boolean,
   val isExpanded: Boolean,
   val isMarkerLine: Boolean
-- 
GitLab