blob: 23d7f232c1c1df6f793d9269b277f416be4301cc [file] [log] [blame]
Stepan Salenikovichd2cad062016-01-08 13:43:49 -05001/*
Guillaume Roguez77c579d2018-01-30 15:54:02 -05002 * Copyright (C) 2016-2018 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 Blin05317a72018-02-21 11:09:16 -0500300 webkit_chat_container_print_history(
301 WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
302 priv->conversation_->interactions
303 );
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400304
305 QObject::disconnect(priv->new_interaction_connection);
306}
307
308static void
309update_add_to_conversations(ChatView *self)
Sébastien Blinf3681aa2017-07-19 16:53:49 -0400310{
311 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
312
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500313 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400314 auto participant = priv->conversation_->participants[0];
Guillaume Roguezc2095922017-12-14 14:07:10 -0500315 try {
316 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(participant);
317 if(contactInfo.profileInfo.type != lrc::api::profile::Type::TEMPORARY
318 && contactInfo.profileInfo.type != lrc::api::profile::Type::PENDING)
319 gtk_widget_hide(priv->button_add_to_conversations);
320 } catch (const std::out_of_range&) {
321 // ContactModel::getContact() exception
322 }
Stepan Salenikovich5039c9b2016-02-12 14:09:51 -0500323}
324
325static void
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500326update_contact_methods(ChatView *self)
327{
328 g_return_if_fail(IS_CHAT_VIEW(self));
329 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500330 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400331 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500332 try {
333 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
334 auto bestId = std::string(contactInfo.registeredName).empty() ? contactInfo.profileInfo.uri : contactInfo.registeredName;
335 if (contactInfo.profileInfo.alias == bestId) {
336 gtk_widget_hide(priv->label_cm);
337 } else {
338 gtk_label_set_text(GTK_LABEL(priv->label_cm), bestId.c_str());
339 gtk_widget_show(priv->label_cm);
340 }
341 } catch (const std::out_of_range&) {
342 // ContactModel::getContact() exception
AmarOkcba03952017-07-17 10:13:49 -0400343 }
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500344}
345
346static void
Sébastien Blinf3681aa2017-07-19 16:53:49 -0400347update_name(ChatView *self)
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500348{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400349 g_return_if_fail(IS_CHAT_VIEW(self));
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500350 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500351 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400352 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500353 try {
354 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
355 auto alias = contactInfo.profileInfo.alias;
356 alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end());
357 gtk_label_set_text(GTK_LABEL(priv->label_peer), alias.c_str());
358 } catch (const std::out_of_range&) {
359 // ContactModel::getContact() exception
360 }
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500361}
362
aviau039001d2016-09-29 16:39:05 -0400363static void
aviau039001d2016-09-29 16:39:05 -0400364webkit_chat_container_ready(ChatView* self)
365{
366 /* The webkit chat container has loaded the javascript libraries, we can
367 * now use it. */
368
369 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
370
371 webkit_chat_container_clear(
372 WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)
373 );
374
Sébastien Blin70dc0b72017-07-31 16:24:41 -0400375 display_links_toggled(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400376 print_text_recording(self);
377 load_participants_images(self);
Sébastien Blin70dc0b72017-07-31 16:24:41 -0400378
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400379 priv->new_interaction_connection = QObject::connect(
Nicolas Jager6635b0d2018-01-24 12:25:28 -0500380 &*priv->accountContainer_->info.conversationModel, &lrc::api::ConversationModel::newInteraction,
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400381 [self, priv](const std::string& uid, uint64_t interactionId, lrc::api::interaction::Info interaction) {
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500382 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400383 if(uid == priv->conversation_->uid) {
384 print_interaction_to_buffer(self, interactionId, interaction);
385 }
386 });
387
388 priv->update_interaction_connection = QObject::connect(
389 &*priv->accountContainer_->info.conversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
390 [self, priv](const std::string& uid, uint64_t msgId, lrc::api::interaction::Info msg) {
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500391 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400392 if(uid == priv->conversation_->uid) {
393 update_interaction(self, msgId, msg);
394 }
395 });
396
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500397 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400398 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500399 try {
400 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
401 priv->isTemporary_ = contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY
402 || contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING;
403 webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
404 auto bestName = contactInfo.profileInfo.alias;
405 if (bestName.empty())
406 bestName = contactInfo.registeredName;
407 if (bestName.empty())
408 bestName = contactInfo.profileInfo.uri;
409 bestName.erase(std::remove(bestName.begin(), bestName.end(), '\r'), bestName.end());
410 webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
411 (contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING),
412 bestName);
413 webkit_chat_disable_send_interaction(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
414 (contactInfo.profileInfo.type == lrc::api::profile::Type::SIP)
415 && priv->conversation_->callId.empty());
416 } catch (const std::out_of_range&) {
417 // ContactModel::getContact() exception
418 }
aviau039001d2016-09-29 16:39:05 -0400419}
420
421static void
422build_chat_view(ChatView* self)
423{
424 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
425
426 gtk_container_add(GTK_CONTAINER(priv->box_webkit_chat_container), priv->webkit_chat_container);
427 gtk_widget_show(priv->webkit_chat_container);
428
Sébastien Blinf3681aa2017-07-19 16:53:49 -0400429 update_name(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400430 update_add_to_conversations(self);
Stepan Salenikovich1f731212016-11-10 11:55:10 -0500431 update_contact_methods(self);
Stepan Salenikovich1f731212016-11-10 11:55:10 -0500432
433 priv->webkit_ready = g_signal_connect_swapped(
aviau039001d2016-09-29 16:39:05 -0400434 priv->webkit_chat_container,
435 "ready",
436 G_CALLBACK(webkit_chat_container_ready),
437 self
438 );
439
AmarOkb4253242017-07-13 11:21:39 -0400440 priv->webkit_send_text = g_signal_connect(priv->webkit_chat_container,
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400441 "script-dialog",
442 G_CALLBACK(webkit_chat_container_script_dialog),
AmarOkb4253242017-07-13 11:21:39 -0400443 self);
444
aviau039001d2016-09-29 16:39:05 -0400445 if (webkit_chat_container_is_ready(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)))
aviau039001d2016-09-29 16:39:05 -0400446 webkit_chat_container_ready(self);
aviau039001d2016-09-29 16:39:05 -0400447
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400448 gtk_widget_set_visible(priv->hbox_chat_info, TRUE);
449
aviau039001d2016-09-29 16:39:05 -0400450}
451
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500452GtkWidget *
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400453chat_view_new (WebKitChatContainer* webkit_chat_container,
454 AccountContainer* accountContainer,
455 lrc::api::conversation::Info* conversation)
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500456{
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500457 ChatView *self = CHAT_VIEW(g_object_new(CHAT_VIEW_TYPE, NULL));
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500458
aviau039001d2016-09-29 16:39:05 -0400459 ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
460 priv->webkit_chat_container = GTK_WIDGET(webkit_chat_container);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400461 priv->conversation_ = conversation;
462 priv->accountContainer_ = accountContainer;
aviau039001d2016-09-29 16:39:05 -0400463
464 build_chat_view(self);
Stepan Salenikovichd2cad062016-01-08 13:43:49 -0500465 return (GtkWidget *)self;
466}
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500467
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400468void
469chat_view_update_temporary(ChatView* self, bool newValue)
Stepan Salenikovichc6a3b982016-01-11 18:11:39 -0500470{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400471 g_return_if_fail(IS_CHAT_VIEW(self));
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400472 auto priv = CHAT_VIEW_GET_PRIVATE(self);
473
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400474 priv->isTemporary_ = newValue;
475 if (!priv->isTemporary_) {
476 gtk_widget_hide(priv->button_add_to_conversations);
477 }
478 webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
Sébastien Blin5851aaf2017-11-06 16:02:08 -0500479 if (!priv->conversation_) return;
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400480 auto contactUri = priv->conversation_->participants.front();
Guillaume Roguezc2095922017-12-14 14:07:10 -0500481 try {
482 auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
483 auto bestName = contactInfo.profileInfo.alias;
484 if (bestName.empty())
485 bestName = contactInfo.registeredName;
486 if (bestName.empty())
487 bestName = contactInfo.profileInfo.uri;
488 webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
489 newValue,
490 bestName);
491 } catch (const std::out_of_range&) {
492 // ContactModel::getContact() exception
493 }
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400494}
495
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400496bool
497chat_view_get_temporary(ChatView *self)
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400498{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400499 g_return_val_if_fail(IS_CHAT_VIEW(self), false);
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400500 auto priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400501 return priv->isTemporary_;
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400502}
503
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400504lrc::api::conversation::Info
505chat_view_get_conversation(ChatView *self)
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400506{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400507 g_return_val_if_fail(IS_CHAT_VIEW(self), lrc::api::conversation::Info());
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400508 auto priv = CHAT_VIEW_GET_PRIVATE(self);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400509 return *priv->conversation_;
Stepan Salenikovich09e0b782016-09-07 16:28:50 -0400510}
Stepan Salenikovichdaf3cb32016-10-12 16:39:42 -0400511
512void
513chat_view_set_header_visible(ChatView *self, gboolean visible)
514{
515 auto priv = CHAT_VIEW_GET_PRIVATE(self);
Stepan Salenikovichdaf3cb32016-10-12 16:39:42 -0400516 gtk_widget_set_visible(priv->hbox_chat_info, visible);
517}