blob: 9489dfd4d90da522dd36c23b69507cb86d6b4c95 [file] [log] [blame]
Stepan Salenikovichd2cad062016-01-08 13:43:49 -05001/*
Guillaume Roguez2a6150d2017-07-19 18:24:47 -04002 * Copyright (C) 2016-2017 Savoir-faire Linux Inc.
Stepan Salenikovichd2cad062016-01-08 13:43:49 -05003 * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
aviau039001d2016-09-29 16:39:05 -04004 * Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
Sébastien Blin55bff9d2017-10-03 15:15:23 -04005 * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com>
6 * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
Stepan Salenikovichd2cad062016-01-08 13:43:49 -05007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#include "chatview.h"
24
Sébastien Blin55bff9d2017-10-03 15:15:23 -040025// std
26#include <algorithm>
Stepan Salenikovichd2cad062016-01-08 13:43:49 -050027
Nicolas Jager759faea2017-03-22 16:22:00 -040028// LRC
Sébastien Blin55bff9d2017-10-03 15:15:23 -040029#include <api/contactmodel.h>
30#include <api/conversationmodel.h>
31#include <api/contact.h>
Nicolas Jager759faea2017-03-22 16:22:00 -040032
Sébastien Blin55bff9d2017-10-03 15:15:23 -040033// Client
34#include "utils/files.h"
Stepan Salenikovichce06adb2016-02-19 12:53:53 -050035
Stepan Salenikovichd2cad062016-01-08 13:43:49 -050036struct _ChatView
37{
38 GtkBox parent;
39};
40
41struct _ChatViewClass
42{
43 GtkBoxClass parent_class;
44};
45
46typedef struct _ChatViewPrivate ChatViewPrivate;
47
48struct _ChatViewPrivate
49{
aviau039001d2016-09-29 16:39:05 -040050 GtkWidget *box_webkit_chat_container;
51 GtkWidget *webkit_chat_container;
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -050052 GtkWidget *hbox_chat_info;
53 GtkWidget *label_peer;
AmarOkcba03952017-07-17 10:13:49 -040054 GtkWidget *label_cm;
Stepan Salenikovich8043a562016-03-18 13:56:40 -040055 GtkWidget *button_close_chatview;
Stepan Salenikoviche9933242016-06-21 18:08:48 -040056 GtkWidget *button_placecall;
Sébastien Blin55bff9d2017-10-03 15:15:23 -040057 GtkWidget *button_add_to_conversations;
Nicolas Jagerd29ae952017-12-04 16:00:12 -050058 GtkWidget *button_place_audio_call;
Stepan Salenikovichd2cad062016-01-08 13:43:49 -050059
Sébastien Blin70dc0b72017-07-31 16:24:41 -040060 GSettings *settings;
61
Sébastien Blin55bff9d2017-10-03 15:15:23 -040062 lrc::api::conversation::Info* conversation_;
63 AccountContainer* accountContainer_;
64 bool isTemporary_;
Stepan Salenikovichd2cad062016-01-08 13:43:49 -050065
Sébastien Blin55bff9d2017-10-03 15:15:23 -040066 QMetaObject::Connection new_interaction_connection;
67 QMetaObject::Connection update_interaction_connection;
68 QMetaObject::Connection update_add_to_conversations;
Stepan Salenikovich1f731212016-11-10 11:55:10 -050069
70 gulong webkit_ready;
AmarOkb4253242017-07-13 11:21:39 -040071 gulong webkit_send_text;
Stepan Salenikovichd2cad062016-01-08 13:43:49 -050072};
73
74G_DEFINE_TYPE_WITH_PRIVATE(ChatView, chat_view, GTK_TYPE_BOX);
75
76#define CHAT_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CHAT_VIEW_TYPE, ChatViewPrivate))
77
78enum {
79 NEW_MESSAGES_DISPLAYED,
Stepan Salenikovich8043a562016-03-18 13:56:40 -040080 HIDE_VIEW_CLICKED,
Stepan Salenikovichd2cad062016-01-08 13:43:49 -050081 LAST_SIGNAL
82};
83
84static guint chat_view_signals[LAST_SIGNAL] = { 0 };
85
86static void
87chat_view_dispose(GObject *object)
88{
89 ChatView *view;
90 ChatViewPrivate *priv;
91
92 view = CHAT_VIEW(object);
93 priv = CHAT_VIEW_GET_PRIVATE(view);
94
Sébastien Blin55bff9d2017-10-03 15:15:23 -040095 QObject::disconnect(priv->new_interaction_connection);
96 QObject::disconnect(priv->update_interaction_connection);
97 QObject::disconnect(priv->update_add_to_conversations);
aviau039001d2016-09-29 16:39:05 -040098
99 /* Destroying the box will also destroy its children, and we wouldn't
100 * want that. So we remove the webkit_chat_container from the box. */
101 if (priv->webkit_chat_container) {
Stepan Salenikovich1f731212016-11-10 11:55:10 -0500102 /* disconnect for webkit signals */
103 g_signal_handler_disconnect(priv->webkit_chat_container, priv->webkit_ready);
104 priv->webkit_ready = 0;
AmarOkb4253242017-07-13 11:21:39 -0400105 g_signal_handler_disconnect(priv->webkit_chat_container, priv->webkit_send_text);
106 priv->webkit_send_text = 0;
Stepan Salenikovich1f731212016-11-10 11:55:10 -0500107
aviau039001d2016-09-29 16:39:05 -0400108 gtk_container_remove(
109 GTK_CONTAINER(priv->box_webkit_chat_container),
110 GTK_WIDGET(priv->webkit_chat_container)
111 );
112 priv->webkit_chat_container = nullptr;
113 }
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500114
115 G_OBJECT_CLASS(chat_view_parent_class)->dispose(object);
116}
117
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500118static void
Stepan Salenikovich8043a562016-03-18 13:56:40 -0400119hide_chat_view(G_GNUC_UNUSED GtkWidget *widget, ChatView *self)
120{
121 g_signal_emit(G_OBJECT(self), chat_view_signals[HIDE_VIEW_CLICKED], 0);
122}
123
124static void
Sébastien Blin70dc0b72017-07-31 16:24:41 -0400125display_links_toggled(ChatView *self)
126{
127 auto priv = CHAT_VIEW_GET_PRIVATE(self);
128 if (priv->webkit_chat_container) {
129 webkit_chat_container_set_display_links(
130 WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
131 g_settings_get_boolean(priv->settings, "enable-display-links")
132 );
133 }
134}
135
136static void
Stepan Salenikoviche9933242016-06-21 18:08:48 -0400137placecall_clicked(ChatView *self)
138{
139 auto priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500140 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400141 priv->accountContainer_->info.conversationModel->placeCall(priv->conversation_->uid);
Stepan Salenikoviche9933242016-06-21 18:08:48 -0400142}
143
144static void
Nicolas Jagerd29ae952017-12-04 16:00:12 -0500145place_audio_call_clicked(ChatView *self)
146{
147 auto priv = CHAT_VIEW_GET_PRIVATE(self);
148
149 if (!priv->conversation_)
150 return;
151
152 priv->accountContainer_->info.conversationModel->placeAudioOnlyCall(priv->conversation_->uid);
153}
154
155static void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400156button_add_to_conversations_clicked(ChatView *self)
Nicolas Jager759faea2017-03-22 16:22:00 -0400157{
158 auto priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500159 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400160 priv->accountContainer_->info.conversationModel->makePermanent(priv->conversation_->uid);
Nicolas Jager759faea2017-03-22 16:22:00 -0400161}
162
163static void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400164webkit_chat_container_script_dialog(G_GNUC_UNUSED GtkWidget* webview, gchar *interaction, ChatView* self)
AmarOkb4253242017-07-13 11:21:39 -0400165{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400166 auto priv = CHAT_VIEW_GET_PRIVATE(self);
167 auto order = std::string(interaction);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500168 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400169 if (order == "ACCEPT") {
170 priv->accountContainer_->info.conversationModel->makePermanent(priv->conversation_->uid);
171 } else if (order == "REFUSE") {
172 priv->accountContainer_->info.conversationModel->removeConversation(priv->conversation_->uid);
173 } else if (order == "BLOCK") {
174 priv->accountContainer_->info.conversationModel->removeConversation(priv->conversation_->uid, true);
175 } else if (order.find("SEND:") == 0) {
176 // Get text body
177 auto toSend = order.substr(std::string("SEND:").size());
178 priv->accountContainer_->info.conversationModel->sendMessage(priv->conversation_->uid, toSend);
AmarOkb4253242017-07-13 11:21:39 -0400179 }
180}
181
182static void
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500183chat_view_init(ChatView *view)
184{
185 gtk_widget_init_template(GTK_WIDGET(view));
186
187 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(view);
Sébastien Blin70dc0b72017-07-31 16:24:41 -0400188 priv->settings = g_settings_new_full(get_ring_schema(), NULL, NULL);
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500189
Stepan Salenikovich8043a562016-03-18 13:56:40 -0400190 g_signal_connect(priv->button_close_chatview, "clicked", G_CALLBACK(hide_chat_view), view);
Stepan Salenikoviche9933242016-06-21 18:08:48 -0400191 g_signal_connect_swapped(priv->button_placecall, "clicked", G_CALLBACK(placecall_clicked), view);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400192 g_signal_connect_swapped(priv->button_add_to_conversations, "clicked", G_CALLBACK(button_add_to_conversations_clicked), view);
Nicolas Jagerd29ae952017-12-04 16:00:12 -0500193 g_signal_connect_swapped(priv->button_place_audio_call, "clicked", G_CALLBACK(place_audio_call_clicked), view);
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500194}
195
196static void
197chat_view_class_init(ChatViewClass *klass)
198{
199 G_OBJECT_CLASS(klass)->dispose = chat_view_dispose;
200
201 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
202 "/cx/ring/RingGnome/chatview.ui");
203
aviau039001d2016-09-29 16:39:05 -0400204 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, box_webkit_chat_container);
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500205 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, hbox_chat_info);
206 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, label_peer);
AmarOkcba03952017-07-17 10:13:49 -0400207 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, label_cm);
Stepan Salenikovich8043a562016-03-18 13:56:40 -0400208 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, button_close_chatview);
Stepan Salenikoviche9933242016-06-21 18:08:48 -0400209 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, button_placecall);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400210 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, button_add_to_conversations);
Nicolas Jagerd29ae952017-12-04 16:00:12 -0500211 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, button_place_audio_call);
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500212
213 chat_view_signals[NEW_MESSAGES_DISPLAYED] = g_signal_new (
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400214 "new-interactions-displayed",
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500215 G_TYPE_FROM_CLASS(klass),
216 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
217 0,
218 nullptr,
219 nullptr,
220 g_cclosure_marshal_VOID__VOID,
221 G_TYPE_NONE, 0);
Stepan Salenikovich8043a562016-03-18 13:56:40 -0400222
223 chat_view_signals[HIDE_VIEW_CLICKED] = g_signal_new (
224 "hide-view-clicked",
225 G_TYPE_FROM_CLASS(klass),
226 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
227 0,
228 nullptr,
229 nullptr,
230 g_cclosure_marshal_VOID__VOID,
231 G_TYPE_NONE, 0);
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500232}
233
234static void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400235print_interaction_to_buffer(ChatView* self, uint64_t interactionId, const lrc::api::interaction::Info& interaction)
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500236{
aviau039001d2016-09-29 16:39:05 -0400237 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
238
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500239 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400240 if (interaction.status == lrc::api::interaction::Status::UNREAD)
241 priv->accountContainer_->info.conversationModel->setInteractionRead(priv->conversation_->uid, interactionId);
242
243 webkit_chat_container_print_new_interaction(
aviau039001d2016-09-29 16:39:05 -0400244 WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400245 interactionId,
246 interaction
aviau039001d2016-09-29 16:39:05 -0400247 );
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500248}
249
aviaufc213552016-11-01 12:39:39 -0400250static void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400251update_interaction(ChatView* self, uint64_t interactionId, const lrc::api::interaction::Info& interaction)
aviaufc213552016-11-01 12:39:39 -0400252{
253 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400254 webkit_chat_container_update_interaction(
255 WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
256 interactionId,
257 interaction
aviaufc213552016-11-01 12:39:39 -0400258 );
aviaufc213552016-11-01 12:39:39 -0400259}
260
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500261static void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400262load_participants_images(ChatView *self)
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500263{
264 g_return_if_fail(IS_CHAT_VIEW(self));
265 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
266
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400267 // Contact
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500268 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400269 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500270 try{
271 auto& contact = priv->accountContainer_->info.contactModel->getContact(contactUri);
272 if (!contact.profileInfo.avatar.empty()) {
273 webkit_chat_container_set_sender_image(
274 WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
275 priv->accountContainer_->info.contactModel->getContactProfileId(contactUri),
276 contact.profileInfo.avatar
277 );
278 }
279 } catch (const std::out_of_range&) {
280 // ContactModel::getContact() exception
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500281 }
282
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400283 // For this account
284 if (!priv->accountContainer_->info.profileInfo.avatar.empty()) {
285 webkit_chat_container_set_sender_image(
286 WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
287 priv->accountContainer_->info.contactModel->getContactProfileId(priv->accountContainer_->info.profileInfo.uri),
288 priv->accountContainer_->info.profileInfo.avatar
289 );
290 }
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500291}
292
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500293static void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400294print_text_recording(ChatView *self)
295{
296 g_return_if_fail(IS_CHAT_VIEW(self));
297 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
298
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500299 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400300 for (const auto& interaction : priv->conversation_->interactions)
301 print_interaction_to_buffer(self, interaction.first, interaction.second);
302
303 QObject::disconnect(priv->new_interaction_connection);
304}
305
306static void
307update_add_to_conversations(ChatView *self)
Sébastien Blinf3681aa2017-07-19 16:53:49 -0400308{
309 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
310
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500311 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400312 auto participant = priv->conversation_->participants[0];
Guillaume Roguezc2095922017-12-14 14:07:10 -0500313 try {
314 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(participant);
315 if(contactInfo.profileInfo.type != lrc::api::profile::Type::TEMPORARY
316 && contactInfo.profileInfo.type != lrc::api::profile::Type::PENDING)
317 gtk_widget_hide(priv->button_add_to_conversations);
318 } catch (const std::out_of_range&) {
319 // ContactModel::getContact() exception
320 }
Stepan Salenikovich5039c9b2016-02-12 14:09:51 -0500321}
322
323static void
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500324update_contact_methods(ChatView *self)
325{
326 g_return_if_fail(IS_CHAT_VIEW(self));
327 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500328 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400329 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500330 try {
331 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
332 auto bestId = std::string(contactInfo.registeredName).empty() ? contactInfo.profileInfo.uri : contactInfo.registeredName;
333 if (contactInfo.profileInfo.alias == bestId) {
334 gtk_widget_hide(priv->label_cm);
335 } else {
336 gtk_label_set_text(GTK_LABEL(priv->label_cm), bestId.c_str());
337 gtk_widget_show(priv->label_cm);
338 }
339 } catch (const std::out_of_range&) {
340 // ContactModel::getContact() exception
AmarOkcba03952017-07-17 10:13:49 -0400341 }
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500342}
343
344static void
Sébastien Blinf3681aa2017-07-19 16:53:49 -0400345update_name(ChatView *self)
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500346{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400347 g_return_if_fail(IS_CHAT_VIEW(self));
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500348 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500349 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400350 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500351 try {
352 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
353 auto alias = contactInfo.profileInfo.alias;
354 alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end());
355 gtk_label_set_text(GTK_LABEL(priv->label_peer), alias.c_str());
356 } catch (const std::out_of_range&) {
357 // ContactModel::getContact() exception
358 }
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500359}
360
aviau039001d2016-09-29 16:39:05 -0400361static void
aviau039001d2016-09-29 16:39:05 -0400362webkit_chat_container_ready(ChatView* self)
363{
364 /* The webkit chat container has loaded the javascript libraries, we can
365 * now use it. */
366
367 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
368
369 webkit_chat_container_clear(
370 WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)
371 );
372
Sébastien Blin70dc0b72017-07-31 16:24:41 -0400373 display_links_toggled(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400374 print_text_recording(self);
375 load_participants_images(self);
Sébastien Blin70dc0b72017-07-31 16:24:41 -0400376
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400377 priv->new_interaction_connection = QObject::connect(
378 &*priv->accountContainer_->info.conversationModel, &lrc::api::ConversationModel::newUnreadMessage,
379 [self, priv](const std::string& uid, uint64_t interactionId, lrc::api::interaction::Info interaction) {
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500380 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400381 if(uid == priv->conversation_->uid) {
382 print_interaction_to_buffer(self, interactionId, interaction);
383 }
384 });
385
386 priv->update_interaction_connection = QObject::connect(
387 &*priv->accountContainer_->info.conversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
388 [self, priv](const std::string& uid, uint64_t msgId, lrc::api::interaction::Info msg) {
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500389 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400390 if(uid == priv->conversation_->uid) {
391 update_interaction(self, msgId, msg);
392 }
393 });
394
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500395 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400396 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500397 try {
398 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
399 priv->isTemporary_ = contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY
400 || contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING;
401 webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
402 auto bestName = contactInfo.profileInfo.alias;
403 if (bestName.empty())
404 bestName = contactInfo.registeredName;
405 if (bestName.empty())
406 bestName = contactInfo.profileInfo.uri;
407 bestName.erase(std::remove(bestName.begin(), bestName.end(), '\r'), bestName.end());
408 webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
409 (contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING),
410 bestName);
411 webkit_chat_disable_send_interaction(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
412 (contactInfo.profileInfo.type == lrc::api::profile::Type::SIP)
413 && priv->conversation_->callId.empty());
414 } catch (const std::out_of_range&) {
415 // ContactModel::getContact() exception
416 }
aviau039001d2016-09-29 16:39:05 -0400417}
418
419static void
420build_chat_view(ChatView* self)
421{
422 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
423
424 gtk_container_add(GTK_CONTAINER(priv->box_webkit_chat_container), priv->webkit_chat_container);
425 gtk_widget_show(priv->webkit_chat_container);
426
Sébastien Blinf3681aa2017-07-19 16:53:49 -0400427 update_name(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400428 update_add_to_conversations(self);
Stepan Salenikovich1f731212016-11-10 11:55:10 -0500429 update_contact_methods(self);
Stepan Salenikovich1f731212016-11-10 11:55:10 -0500430
431 priv->webkit_ready = g_signal_connect_swapped(
aviau039001d2016-09-29 16:39:05 -0400432 priv->webkit_chat_container,
433 "ready",
434 G_CALLBACK(webkit_chat_container_ready),
435 self
436 );
437
AmarOkb4253242017-07-13 11:21:39 -0400438 priv->webkit_send_text = g_signal_connect(priv->webkit_chat_container,
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400439 "script-dialog",
440 G_CALLBACK(webkit_chat_container_script_dialog),
AmarOkb4253242017-07-13 11:21:39 -0400441 self);
442
aviau039001d2016-09-29 16:39:05 -0400443 if (webkit_chat_container_is_ready(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)))
aviau039001d2016-09-29 16:39:05 -0400444 webkit_chat_container_ready(self);
aviau039001d2016-09-29 16:39:05 -0400445
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400446 gtk_widget_set_visible(priv->hbox_chat_info, TRUE);
447
aviau039001d2016-09-29 16:39:05 -0400448}
449
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500450GtkWidget *
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400451chat_view_new (WebKitChatContainer* webkit_chat_container,
452 AccountContainer* accountContainer,
453 lrc::api::conversation::Info* conversation)
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500454{
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500455 ChatView *self = CHAT_VIEW(g_object_new(CHAT_VIEW_TYPE, NULL));
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500456
aviau039001d2016-09-29 16:39:05 -0400457 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
458 priv->webkit_chat_container = GTK_WIDGET(webkit_chat_container);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400459 priv->conversation_ = conversation;
460 priv->accountContainer_ = accountContainer;
aviau039001d2016-09-29 16:39:05 -0400461
462 build_chat_view(self);
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500463 return (GtkWidget *)self;
464}
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500465
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400466void
467chat_view_update_temporary(ChatView* self, bool newValue)
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500468{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400469 g_return_if_fail(IS_CHAT_VIEW(self));
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400470 auto priv = CHAT_VIEW_GET_PRIVATE(self);
471
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400472 priv->isTemporary_ = newValue;
473 if (!priv->isTemporary_) {
474 gtk_widget_hide(priv->button_add_to_conversations);
475 }
476 webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500477 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400478 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500479 try {
480 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
481 auto bestName = contactInfo.profileInfo.alias;
482 if (bestName.empty())
483 bestName = contactInfo.registeredName;
484 if (bestName.empty())
485 bestName = contactInfo.profileInfo.uri;
486 webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
487 newValue,
488 bestName);
489 } catch (const std::out_of_range&) {
490 // ContactModel::getContact() exception
491 }
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400492}
493
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400494bool
495chat_view_get_temporary(ChatView *self)
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400496{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400497 g_return_val_if_fail(IS_CHAT_VIEW(self), false);
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400498 auto priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400499 return priv->isTemporary_;
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400500}
501
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400502lrc::api::conversation::Info
503chat_view_get_conversation(ChatView *self)
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400504{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400505 g_return_val_if_fail(IS_CHAT_VIEW(self), lrc::api::conversation::Info());
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400506 auto priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400507 return *priv->conversation_;
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400508}
Stepan Salenikovichdaf3cb32016-10-12 16:39:42 -0400509
510void
511chat_view_set_header_visible(ChatView *self, gboolean visible)
512{
513 auto priv = CHAT_VIEW_GET_PRIVATE(self);
Stepan Salenikovichdaf3cb32016-10-12 16:39:42 -0400514 gtk_widget_set_visible(priv->hbox_chat_info, visible);
515}