From 6bbfd8767b44168d175a6660dd4513dc79fbe549 Mon Sep 17 00:00:00 2001
From: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>
Date: Tue, 1 May 2018 12:41:29 -0400
Subject: [PATCH] chatview: clearly display banned contacts as such
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Whenever the chat view has to display a banned contact, it should:
- Make place call, add to contacts and place audio call buttons
  unclickable
- Hide the send message bar
- Display the banned contact as such in the smart list results (grey bg,
  bold "Banned contact", etc.)

This patch implements this behavior in the GNU/Linux GNOME client.

For the moment the conversation popup is still mentioning invalid
options such as «block contact» or «place call», but since fixing it
requires LRC side changes we will address this issue in a separate
commit.

Change-Id: Ibc8da7d755319acae59a807cc248e3a87bd9d6da
Reviewed-by: Sebastien Blin <sebastien.blin@savoirfairelinux.com>
---
 src/chatview.cpp            | 30 ++++++++++++++++++++++-
 src/conversationsview.cpp   | 47 ++++++++++++++++++++++++++++++++++---
 src/webkitchatcontainer.cpp | 14 +++++++++++
 src/webkitchatcontainer.h   |  1 +
 web/chatview.html           | 13 ++++++++++
 5 files changed, 101 insertions(+), 4 deletions(-)

diff --git a/src/chatview.cpp b/src/chatview.cpp
index d36e759e..80925f98 100644
--- a/src/chatview.cpp
+++ b/src/chatview.cpp
@@ -396,6 +396,34 @@ print_text_recording(ChatView *self)
     QObject::disconnect(priv->new_interaction_connection);
 }
 
+static void
+update_if_banned(ChatView *self)
+{
+    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
+
+    if (!priv->conversation_) return;
+    auto participant = priv->conversation_->participants[0];
+    try {
+        auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(participant);
+        if (contactInfo.isBanned) {
+            gtk_widget_set_sensitive (priv->button_placecall, FALSE);
+            gtk_widget_set_tooltip_text(priv->button_placecall, _("Can't place call with banned contact"));
+            gtk_widget_set_sensitive (priv->button_add_to_conversations, FALSE);
+            gtk_widget_set_tooltip_text(priv->button_add_to_conversations, _("Can't start conversation with banned contact"));
+            gtk_widget_set_sensitive (priv->button_place_audio_call, FALSE);
+            gtk_widget_set_tooltip_text(priv->button_place_audio_call, _("Can't place audio call with banned contact"));
+            webkit_chat_hide_message_bar(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), true);
+        } else {
+            gtk_widget_set_sensitive (priv->button_placecall, TRUE);
+            gtk_widget_set_sensitive (priv->button_add_to_conversations, TRUE);
+            gtk_widget_set_sensitive (priv->button_place_audio_call, TRUE);
+            webkit_chat_hide_message_bar(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), false);
+        }
+    } catch (const std::out_of_range&) {
+        // ContactModel::getContact() exception
+    }
+}
+
 static void
 update_add_to_conversations(ChatView *self)
 {
@@ -520,6 +548,7 @@ build_chat_view(ChatView* self)
     update_name(self);
     update_add_to_conversations(self);
     update_contact_methods(self);
+    update_if_banned(self);
 
     priv->webkit_ready = g_signal_connect_swapped(
         priv->webkit_chat_container,
@@ -537,7 +566,6 @@ build_chat_view(ChatView* self)
         webkit_chat_container_ready(self);
 
     gtk_widget_set_visible(priv->hbox_chat_info, TRUE);
-
 }
 
 GtkWidget *
diff --git a/src/conversationsview.cpp b/src/conversationsview.cpp
index 2089da88..9fae1ce2 100644
--- a/src/conversationsview.cpp
+++ b/src/conversationsview.cpp
@@ -102,6 +102,13 @@ render_contact_photo(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
         // so that the other renderers are shifted to the right
         g_object_set(G_OBJECT(cell), "width", 50, NULL);
         g_object_set(G_OBJECT(cell), "pixbuf", image.get(), NULL);
+
+        // Banned contacts should be displayed with grey bg
+        if (contactInfo.isBanned) {
+            g_object_set(G_OBJECT(cell), "cell-background", "#BDBDBD", NULL);
+        } else {
+            g_object_set(G_OBJECT(cell), "cell-background", NULL, NULL);
+        }
     }
     catch (const std::exception&)
     {
@@ -114,7 +121,7 @@ render_name_and_last_interaction(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
                                  GtkCellRenderer *cell,
                                  GtkTreeModel *model,
                                  GtkTreeIter *iter,
-                                 G_GNUC_UNUSED GtkTreeView *treeview)
+                                 GtkTreeView *treeview)
 {
     gchar *alias;
     gchar *registeredName;
@@ -123,6 +130,18 @@ render_name_and_last_interaction(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
     gchar *uid;
     gchar *uri;
 
+    // Get active conversation
+    auto path = gtk_tree_model_get_path(model, iter);
+    auto row = std::atoi(gtk_tree_path_to_string(path));
+    if (row == -1) return;
+
+    auto priv = CONVERSATIONS_VIEW_GET_PRIVATE(treeview);
+    if (!priv) return;
+
+    auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(row);
+    auto contactUri = conversation.participants.front();
+    auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
+
     gtk_tree_model_get (model, iter,
                         0 /* col# */, &uid /* data */,
                         1 /* col# */, &alias /* data */,
@@ -132,7 +151,13 @@ render_name_and_last_interaction(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
                         -1);
 
     auto bestId = std::string(registeredName).empty() ? uri: registeredName;
-    if (std::string(alias).empty()) {
+    if (contactInfo.isBanned) {
+        // Contact is banned, display it clearly
+        text = g_markup_printf_escaped(
+            "<span font_weight=\"bold\">%s</span>\n<span size=\"smaller\" font_weight=\"bold\">Banned contact</span>",
+            bestId
+        );
+    } else if (std::string(alias).empty()) {
         // For conversations with contacts with no alias
         text = g_markup_printf_escaped(
             "<span font_weight=\"bold\">%s</span>\n<span size=\"smaller\" color=\"#666\">%s</span>",
@@ -157,6 +182,13 @@ render_name_and_last_interaction(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
         );
     }
 
+    // Banned contacts should be displayed with grey bg
+    if (contactInfo.isBanned) {
+        g_object_set(G_OBJECT(cell), "cell-background", "#BDBDBD", NULL);
+    } else {
+        g_object_set(G_OBJECT(cell), "cell-background", NULL, NULL);
+    }
+
     g_object_set(G_OBJECT(cell), "markup", text, NULL);
     g_free(uid);
     g_free(uri);
@@ -185,6 +217,16 @@ render_time(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
     try
     {
         auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(row);
+        auto contactUri = conversation.participants.front();
+        auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
+
+        // Banned contacts should be displayed with grey bg
+        if (contactInfo.isBanned) {
+            g_object_set(G_OBJECT(cell), "cell-background", "#BDBDBD", NULL);
+        } else {
+            g_object_set(G_OBJECT(cell), "cell-background", NULL, NULL);
+        }
+
         auto callId = conversation.confId.empty() ? conversation.callId : conversation.confId;
         if (!callId.empty()) {
             auto call = (*priv->accountInfo_)->callModel->getCall(callId);
@@ -203,7 +245,6 @@ render_time(G_GNUC_UNUSED GtkTreeViewColumn *tree_column,
                 std::strftime(interactionDay, sizeof(interactionDay), "%D", std::localtime(&lastInteractionTimestamp));
                 std::strftime(nowDay, sizeof(nowDay), "%D", std::localtime(&now));
 
-
                 if (std::string(interactionDay) == std::string(nowDay)) {
                     char interactionTime[100];
                     std::strftime(interactionTime, sizeof(interactionTime), "%R", std::localtime(&lastInteractionTimestamp));
diff --git a/src/webkitchatcontainer.cpp b/src/webkitchatcontainer.cpp
index 0c6a4fb5..1c0924cf 100644
--- a/src/webkitchatcontainer.cpp
+++ b/src/webkitchatcontainer.cpp
@@ -566,6 +566,20 @@ webkit_chat_disable_send_interaction(WebKitChatContainer *view, bool isDisabled)
     );
 }
 
+void
+webkit_chat_hide_message_bar(WebKitChatContainer *view, bool isHidden)
+{
+    auto priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
+    gchar* function_call = g_strdup_printf("ring.chatview.hideMessageBar(%s);", isHidden ? "true" : "false");
+
+    webkit_web_view_run_javascript(
+        WEBKIT_WEB_VIEW(priv->webview_chat),
+        function_call,
+        NULL,
+        NULL,
+        NULL
+    );
+}
 
 void
 webkit_chat_container_clear_sender_images(WebKitChatContainer *view)
diff --git a/src/webkitchatcontainer.h b/src/webkitchatcontainer.h
index 6efefdea..0e8aebd1 100644
--- a/src/webkitchatcontainer.h
+++ b/src/webkitchatcontainer.h
@@ -53,6 +53,7 @@ void       webkit_chat_container_set_sender_image     (WebKitChatContainer *view
 gboolean   webkit_chat_container_is_ready             (WebKitChatContainer *view);
 void       webkit_chat_container_set_display_links    (WebKitChatContainer *view, bool display);
 void       webkit_chat_disable_send_interaction       (WebKitChatContainer *view, bool isDisabled);
+void       webkit_chat_hide_message_bar               (WebKitChatContainer *view, bool isHidden);
 void       webkit_chat_container_set_temporary        (WebKitChatContainer *view, bool temporary);
 void       webkit_chat_container_set_invitation       (WebKitChatContainer *view, bool show, const std::string& contactUri);
 
diff --git a/web/chatview.html b/web/chatview.html
index 9505b7b8..227bcfed 100644
--- a/web/chatview.html
+++ b/web/chatview.html
@@ -151,6 +151,18 @@ ring.chatview = (function(){
         input.disabled = isDisabled;
     }
 
+    /**
+     * Change the value of the progress bar
+     */
+    function hideMessageBar(isHidden) {
+        const messageBar = document.querySelector('#sendMessage');
+        if (isHidden) {
+            messageBar.style.visibility = 'hidden';
+        } else {
+            messageBar.style.visibility = 'visible';
+        }
+    }
+
     /**
      * Accept an invite
      */
@@ -1018,6 +1030,7 @@ ring.chatview = (function(){
         blockConversation: blockConversation,
         showInvitation: showInvitation,
         hideInvitation: hideInvitation,
+        hideMessageBar: hideMessageBar,
         disableSendMessage: disableSendMessage,
         updateTimestamps: updateTimestamps,
         sendFile: sendFile,
-- 
GitLab