From e29bf59cf7cbffba545eb445f86c88af901410bd Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Sun, 6 Jan 2019 18:14:42 +0100
Subject: [PATCH] Add user info to message context menu when only one is
 selected

---
 .../ui/chat/messages/MessageListFragment.kt   | 41 +++++++++++++++----
 .../chat/messages/QuasselMessageRenderer.kt   | 34 +++++++--------
 app/src/main/res/menu/context_messages.xml    |  4 ++
 .../viewmodel/QuasselViewModel.kt             |  4 +-
 .../viewmodel/data/FormattedMessage.kt        |  8 ++--
 5 files changed, 60 insertions(+), 31 deletions(-)

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 bfe817fe7..d9c4c2229 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
@@ -120,10 +120,31 @@ class MessageListFragment : ServiceBoundFragment() {
 
   private val actionModeCallback = object : ActionMode.Callback {
     override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?) = when (item?.itemId) {
-      R.id.action_copy  -> {
+      R.id.action_user_info -> {
+        viewModel.selectedMessages.value.values.firstOrNull()?.let { msg ->
+          viewModel.session.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
+            viewModel.bufferData.value?.info?.let(BufferInfo::networkId)?.let { networkId ->
+              UserInfoActivity.launch(
+                requireContext(),
+                openBuffer = false,
+                bufferId = bufferSyncer.find(
+                  bufferName = HostmaskHelper.nick(msg.original.sender),
+                  networkId = networkId,
+                  type = Buffer_Type.of(Buffer_Type.QueryBuffer)
+                )?.let(BufferInfo::bufferId),
+                nick = HostmaskHelper.nick(msg.original.sender),
+                networkId = networkId
+              )
+            }
+          }
+
+          true
+        } ?: false
+      }
+      R.id.action_copy      -> {
         val builder = SpannableStringBuilder()
         viewModel.selectedMessages.value.values.asSequence().sortedBy {
-          it.id
+          it.original.messageId
         }.map {
           if (it.name != null && it.content != null) {
             SpanFormatter.format(getString(R.string.message_format_copy_complex),
@@ -149,10 +170,10 @@ class MessageListFragment : ServiceBoundFragment() {
         actionMode?.finish()
         true
       }
-      R.id.action_share -> {
+      R.id.action_share     -> {
         val builder = SpannableStringBuilder()
         viewModel.selectedMessages.value.values.asSequence().sortedBy {
-          it.id
+          it.original.messageId
         }.map {
           if (it.name != null && it.content != null) {
             SpanFormatter.format(getString(R.string.message_format_copy_complex),
@@ -225,8 +246,10 @@ class MessageListFragment : ServiceBoundFragment() {
 
     adapter.setOnClickListener { msg ->
       if (actionMode != null) {
-        if (!viewModel.selectedMessagesToggle(msg.id, msg)) {
-          actionMode?.finish()
+        when (viewModel.selectedMessagesToggle(msg.original.messageId, msg)) {
+          0    -> actionMode?.finish()
+          1    -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true
+          else -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
         }
       }
     }
@@ -234,8 +257,10 @@ class MessageListFragment : ServiceBoundFragment() {
       if (actionMode == null) {
         activity?.startActionMode(actionModeCallback)
       }
-      if (!viewModel.selectedMessagesToggle(msg.id, msg)) {
-        actionMode?.finish()
+      when (viewModel.selectedMessagesToggle(msg.original.messageId, msg)) {
+        0    -> actionMode?.finish()
+        1    -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true
+        else -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
       }
     }
     if (autoCompleteSettings.senderDoubleClick)
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 2f4f20b7e..6fba346ec 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
@@ -274,7 +274,7 @@ class QuasselMessageRenderer @Inject constructor(
         val senderColor = if (useSelfColor) selfColor else senderColors[senderColorIndex]
 
         FormattedMessage(
-          id = message.content.messageId,
+          original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
           dayChange = formatDayChange(message),
           name = nick,
@@ -308,7 +308,7 @@ class QuasselMessageRenderer @Inject constructor(
         val senderColor = if (useSelfColor) selfColor else senderColors[senderColorIndex]
 
         FormattedMessage(
-          id = message.content.messageId,
+          original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
           dayChange = formatDayChange(message),
           combined = SpanFormatter.format(
@@ -328,7 +328,7 @@ class QuasselMessageRenderer @Inject constructor(
         )
       }
       Message_Type.Notice       -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = SpanFormatter.format(
@@ -347,7 +347,7 @@ class QuasselMessageRenderer @Inject constructor(
       Message_Type.Nick         -> {
         val nickSelf = message.content.sender == message.content.content || self
         FormattedMessage(
-          id = message.content.messageId,
+          original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
           dayChange = formatDayChange(message),
           combined = if (nickSelf) {
@@ -387,7 +387,7 @@ class QuasselMessageRenderer @Inject constructor(
         )
       }
       Message_Type.Mode         -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = SpanFormatter.format(
@@ -402,7 +402,7 @@ class QuasselMessageRenderer @Inject constructor(
         isSelected = message.isSelected
       )
       Message_Type.Join         -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = SpanFormatter.format(
@@ -422,7 +422,7 @@ class QuasselMessageRenderer @Inject constructor(
         isSelected = message.isSelected
       )
       Message_Type.Part         -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = if (message.content.content.isBlank()) {
@@ -457,7 +457,7 @@ class QuasselMessageRenderer @Inject constructor(
         isSelected = message.isSelected
       )
       Message_Type.Quit         -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = if (message.content.content.isBlank()) {
@@ -494,7 +494,7 @@ class QuasselMessageRenderer @Inject constructor(
       Message_Type.Kick         -> {
         val (user, reason) = message.content.content.split(' ', limit = 2) + listOf("", "")
         FormattedMessage(
-          id = message.content.messageId,
+          original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
           dayChange = formatDayChange(message),
           combined = if (reason.isBlank()) {
@@ -530,7 +530,7 @@ class QuasselMessageRenderer @Inject constructor(
       Message_Type.Kill         -> {
         val (user, reason) = message.content.content.split(' ', limit = 2) + listOf("", "")
         FormattedMessage(
-          id = message.content.messageId,
+          original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
           dayChange = formatDayChange(message),
           combined = if (reason.isBlank()) {
@@ -572,7 +572,7 @@ class QuasselMessageRenderer @Inject constructor(
         }
 
         FormattedMessage(
-          id = message.content.messageId,
+          original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
           dayChange = formatDayChange(message),
           combined = context.resources.getQuantityString(
@@ -598,7 +598,7 @@ class QuasselMessageRenderer @Inject constructor(
         }
 
         FormattedMessage(
-          id = message.content.messageId,
+          original = message.content,
           time = timeFormatter.format(message.content.time.atZone(zoneId)),
           dayChange = formatDayChange(message),
           combined = context.resources.getQuantityString(
@@ -618,7 +618,7 @@ class QuasselMessageRenderer @Inject constructor(
       Message_Type.Server,
       Message_Type.Info,
       Message_Type.Error        -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = contentFormatter.formatContent(message.content.content,
@@ -630,7 +630,7 @@ class QuasselMessageRenderer @Inject constructor(
         isSelected = message.isSelected
       )
       Message_Type.Topic        -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = contentFormatter.formatContent(message.content.content,
@@ -642,7 +642,7 @@ class QuasselMessageRenderer @Inject constructor(
         isSelected = message.isSelected
       )
       Message_Type.DayChange    -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = "",
         dayChange = formatDayChange(message),
         combined = dateFormatter.format(message.content.time.atZone(zoneId)),
@@ -652,7 +652,7 @@ class QuasselMessageRenderer @Inject constructor(
         isSelected = false
       )
       Message_Type.Invite       -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = contentFormatter.formatContent(message.content.content,
@@ -664,7 +664,7 @@ class QuasselMessageRenderer @Inject constructor(
         isSelected = message.isSelected
       )
       else                      -> FormattedMessage(
-        id = message.content.messageId,
+        original = message.content,
         time = timeFormatter.format(message.content.time.atZone(zoneId)),
         dayChange = formatDayChange(message),
         combined = SpanFormatter.format(
diff --git a/app/src/main/res/menu/context_messages.xml b/app/src/main/res/menu/context_messages.xml
index 0a0f1a957..d1a2b4e32 100644
--- a/app/src/main/res/menu/context_messages.xml
+++ b/app/src/main/res/menu/context_messages.xml
@@ -18,6 +18,10 @@
   -->
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
+  <item
+    android:id="@+id/action_user_info"
+    android:icon="@drawable/ic_account"
+    android:title="@string/label_info_user" />
   <item
     android:id="@+id/action_copy"
     android:icon="@drawable/ic_copy"
diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
index 843b2b583..d64c71158 100644
--- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
+++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt
@@ -58,11 +58,11 @@ class QuasselViewModel : ViewModel() {
   val backendWrapper = BehaviorSubject.createDefault(Observable.empty<Optional<Backend>>())
 
   val selectedMessages = BehaviorSubject.createDefault(emptyMap<MsgId, FormattedMessage>())
-  fun selectedMessagesToggle(key: MsgId, value: FormattedMessage): Boolean {
+  fun selectedMessagesToggle(key: MsgId, value: FormattedMessage): Int {
     val set = selectedMessages.value.orEmpty()
     val result = if (set.containsKey(key)) set - key else set + Pair(key, value)
     selectedMessages.onNext(result)
-    return result.isNotEmpty()
+    return result.size
   }
 
   val expandedMessages = BehaviorSubject.createDefault(emptySet<MsgId>())
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 c348fc30c..e9b5613e7 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
@@ -20,10 +20,10 @@
 package de.kuschku.quasseldroid.viewmodel.data
 
 import android.graphics.drawable.Drawable
-import de.kuschku.libquassel.protocol.MsgId
+import de.kuschku.quasseldroid.persistence.QuasselDatabase
 
 class FormattedMessage(
-  val id: MsgId,
+  val original: QuasselDatabase.MessageData,
   val time: CharSequence,
   val dayChange: CharSequence? = null,
   val name: CharSequence? = null,
@@ -44,7 +44,7 @@ class FormattedMessage(
 
     other as FormattedMessage
 
-    if (id != other.id) return false
+    if (original != other.original) return false
     if (time != other.time) return false
     if (dayChange != other.dayChange) return false
     if (name != other.name) return false
@@ -62,7 +62,7 @@ class FormattedMessage(
   }
 
   override fun hashCode(): Int {
-    var result = id.hashCode()
+    var result = original.hashCode()
     result = 31 * result + time.hashCode()
     result = 31 * result + (dayChange?.hashCode() ?: 0)
     result = 31 * result + (name?.hashCode() ?: 0)
-- 
GitLab