blob: c630af83767762c84bd288771228fbd69470eb83 [file] [log] [blame]
aviau039001d2016-09-29 16:39:05 -04001/*
Guillaume Roguez2a6150d2017-07-19 18:24:47 -04002 * Copyright (C) 2016-2017 Savoir-faire Linux Inc.
aviau039001d2016-09-29 16:39:05 -04003 * Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
Sébastien Blin55bff9d2017-10-03 15:15:23 -04004 * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
aviau039001d2016-09-29 16:39:05 -04005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include "webkitchatcontainer.h"
22
23// GTK+ related
aviau039001d2016-09-29 16:39:05 -040024#include <webkit2/webkit2.h>
25
26// Qt
27#include <QtCore/QJsonValue>
28#include <QtCore/QJsonObject>
29#include <QtCore/QJsonDocument>
30
31// LRC
aviau039001d2016-09-29 16:39:05 -040032#include <globalinstances.h>
33
34// Ring Client
35#include "native/pixbufmanipulator.h"
aviau039001d2016-09-29 16:39:05 -040036
37struct _WebKitChatContainer
38{
39 GtkBox parent;
40};
41
42struct _WebKitChatContainerClass
43{
44 GtkBoxClass parent_class;
45};
46
47typedef struct _WebKitChatContainerPrivate WebKitChatContainerPrivate;
48
49struct _WebKitChatContainerPrivate
50{
51 GtkWidget* webview_chat;
aviau32b8dd62016-11-02 00:36:57 -040052 GtkWidget* box_webview_chat;
aviau039001d2016-09-29 16:39:05 -040053
54 bool chatview_debug;
55
56 /* Array of javascript libraries to load. Used during initialization */
57 GList* js_libs_to_load;
58 gboolean js_libs_loaded;
59};
60
61G_DEFINE_TYPE_WITH_PRIVATE(WebKitChatContainer, webkit_chat_container, GTK_TYPE_BOX);
62
63#define WEBKIT_CHAT_CONTAINER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), WEBKIT_CHAT_CONTAINER_TYPE, WebKitChatContainerPrivate))
64
65/* signals */
66enum {
67 READY,
Sébastien Blin55bff9d2017-10-03 15:15:23 -040068 SCRIPT_DIALOG,
aviau039001d2016-09-29 16:39:05 -040069 LAST_SIGNAL
70};
71
72static guint webkit_chat_container_signals[LAST_SIGNAL] = { 0 };
73
Stepan Salenikovich1cf35e52017-05-03 16:12:11 -040074/* functions */
75static gboolean webview_crashed(WebKitChatContainer *self);
76
aviau039001d2016-09-29 16:39:05 -040077static void
78webkit_chat_container_dispose(GObject *object)
79{
80 G_OBJECT_CLASS(webkit_chat_container_parent_class)->dispose(object);
81}
82
83static void
84webkit_chat_container_init(WebKitChatContainer *view)
85{
86 gtk_widget_init_template(GTK_WIDGET(view));
87}
88
89static void
90webkit_chat_container_class_init(WebKitChatContainerClass *klass)
91{
92 G_OBJECT_CLASS(klass)->dispose = webkit_chat_container_dispose;
93
aviau039001d2016-09-29 16:39:05 -040094 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
95 "/cx/ring/RingGnome/webkitchatcontainer.ui");
96
aviau32b8dd62016-11-02 00:36:57 -040097 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), WebKitChatContainer, box_webview_chat);
aviau039001d2016-09-29 16:39:05 -040098
99 /* add signals */
100 webkit_chat_container_signals[READY] = g_signal_new("ready",
101 G_TYPE_FROM_CLASS(klass),
102 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
103 0,
104 nullptr,
105 nullptr,
106 g_cclosure_marshal_VOID__VOID,
107 G_TYPE_NONE, 0);
AmarOkb4253242017-07-13 11:21:39 -0400108
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400109 webkit_chat_container_signals[SCRIPT_DIALOG] = g_signal_new("script-dialog",
AmarOkb4253242017-07-13 11:21:39 -0400110 G_TYPE_FROM_CLASS(klass),
111 (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED),
112 0,
113 nullptr,
114 nullptr,
115 g_cclosure_marshal_VOID__STRING,
116 G_TYPE_NONE, 1, G_TYPE_STRING);
aviau039001d2016-09-29 16:39:05 -0400117}
118
119static gboolean
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400120webview_chat_context_menu(G_GNUC_UNUSED WebKitChatContainer *self,
AmarOk748d6cd2017-07-18 12:23:42 -0400121 WebKitContextMenu *menu,
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400122 G_GNUC_UNUSED GdkEvent *event,
123 G_GNUC_UNUSED WebKitHitTestResult *hit_test_result,
124 G_GNUC_UNUSED gpointer user_data)
aviau039001d2016-09-29 16:39:05 -0400125{
AmarOk748d6cd2017-07-18 12:23:42 -0400126 GList *items, *nextList;
127 for (items = webkit_context_menu_get_items(menu) ; items ; items = nextList) {
128 WebKitContextMenuAction action;
129 nextList = items->next;
130 auto item = (WebKitContextMenuItem*)items->data;
131 action = webkit_context_menu_item_get_stock_action(item);
132
133 if (action == WEBKIT_CONTEXT_MENU_ACTION_RELOAD ||
134 action == WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD ||
135 action == WEBKIT_CONTEXT_MENU_ACTION_GO_BACK ||
136 action == WEBKIT_CONTEXT_MENU_ACTION_STOP) {
137 webkit_context_menu_remove(menu, item);
138 }
139 }
140 return false;
aviau039001d2016-09-29 16:39:05 -0400141}
142
143QString
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400144interaction_to_json_interaction_object(const uint64_t msgId, const lrc::api::interaction::Info& interaction)
aviau039001d2016-09-29 16:39:05 -0400145{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400146 auto sender = QString(interaction.authorUri.c_str());
147 auto timestamp = QString::number(interaction.timestamp);
148 auto direction = lrc::api::interaction::isOutgoing(interaction) ? QString("out") : QString("in");
aviau039001d2016-09-29 16:39:05 -0400149
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400150 QJsonObject interaction_object = QJsonObject();
151 interaction_object.insert("text", QJsonValue(QString(interaction.body.c_str())));
152 interaction_object.insert("id", QJsonValue(QString::number(msgId)));
153 interaction_object.insert("sender", QJsonValue(sender));
154 interaction_object.insert("sender_contact_method", QJsonValue(sender));
155 interaction_object.insert("timestamp", QJsonValue(timestamp));
156 interaction_object.insert("direction", QJsonValue(direction));
157 switch (interaction.type)
aviaufc213552016-11-01 12:39:39 -0400158 {
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400159 case lrc::api::interaction::Type::TEXT:
160 interaction_object.insert("type", QJsonValue("text"));
161 break;
162 case lrc::api::interaction::Type::CALL:
163 interaction_object.insert("type", QJsonValue("call"));
164 break;
165 case lrc::api::interaction::Type::CONTACT:
166 interaction_object.insert("type", QJsonValue("contact"));
167 break;
168 case lrc::api::interaction::Type::INVALID:
169 default:
170 interaction_object.insert("type", QJsonValue(""));
171 break;
aviaufc213552016-11-01 12:39:39 -0400172 }
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400173 switch (interaction.status)
aviaufc213552016-11-01 12:39:39 -0400174 {
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400175 case lrc::api::interaction::Status::READ:
176 interaction_object.insert("delivery_status", QJsonValue("read"));
177 break;
178 case lrc::api::interaction::Status::SUCCEED:
179 interaction_object.insert("delivery_status", QJsonValue("sent"));
180 break;
181 case lrc::api::interaction::Status::FAILED:
182 interaction_object.insert("delivery_status", QJsonValue("failure"));
183 break;
184 case lrc::api::interaction::Status::SENDING:
185 interaction_object.insert("delivery_status", QJsonValue("sending"));
186 break;
187 case lrc::api::interaction::Status::INVALID:
188 case lrc::api::interaction::Status::UNKNOWN:
189 case lrc::api::interaction::Status::UNREAD:
190 default:
191 interaction_object.insert("delivery_status", QJsonValue("unknown"));
192 break;
aviaufc213552016-11-01 12:39:39 -0400193 }
194
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400195 return QString(QJsonDocument(interaction_object).toJson(QJsonDocument::Compact));
aviau039001d2016-09-29 16:39:05 -0400196}
197
Stepan Salenikovichb52dbc52016-12-27 14:05:39 -0500198#if WEBKIT_CHECK_VERSION(2, 6, 0)
aviau039001d2016-09-29 16:39:05 -0400199static gboolean
200webview_chat_decide_policy (G_GNUC_UNUSED WebKitWebView *web_view,
201 WebKitPolicyDecision *decision,
202 WebKitPolicyDecisionType type)
203{
204 switch (type)
205 {
206 case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
207 case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
208 {
209 WebKitNavigationPolicyDecision* navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION(decision);
210 WebKitNavigationAction* navigation_action = webkit_navigation_policy_decision_get_navigation_action(navigation_decision);
211 WebKitNavigationType navigation_type = webkit_navigation_action_get_navigation_type(navigation_action);
212
213 switch (navigation_type)
214 {
215 case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED:
216 case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD:
217 case WEBKIT_NAVIGATION_TYPE_RELOAD:
218 case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
219 case WEBKIT_NAVIGATION_TYPE_OTHER:
220 {
221 /* make no decision */
222 return FALSE;
223
224 }
225 case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED:
226 {
227 webkit_policy_decision_ignore(decision);
228
229 WebKitURIRequest* uri_request = webkit_navigation_action_get_request(navigation_action);
230 const gchar* uri = webkit_uri_request_get_uri(uri_request);
231
232 gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, NULL);
233 }
234 }
235
236 webkit_policy_decision_ignore(decision);
237 break;
238 }
239 case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
240 {
241 //WebKitResponsePolicyDecision *response = WEBKIT_RESPONSE_POLICY_DECISION (decision);
242 //break;
243 return FALSE;
244 }
245 default:
246 {
247 /* Making no decision results in webkit_policy_decision_use(). */
248 return FALSE;
249 }
250 }
251 return TRUE;
252}
253#endif
254
AmarOkb4253242017-07-13 11:21:39 -0400255static gboolean
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400256webview_script_dialog(WebKitWebView *self,
257 WebKitScriptDialog *dialog,
258 G_GNUC_UNUSED gpointer user_data)
AmarOkb4253242017-07-13 11:21:39 -0400259{
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400260 auto interaction = webkit_script_dialog_get_message(dialog);
261 g_signal_emit(G_OBJECT(self), webkit_chat_container_signals[SCRIPT_DIALOG], 0, interaction);
AmarOkb4253242017-07-13 11:21:39 -0400262 return true;
263}
264
aviau039001d2016-09-29 16:39:05 -0400265static void
266javascript_library_loaded(WebKitWebView *webview_chat,
267 GAsyncResult *result,
268 WebKitChatContainer* self)
269{
270 g_return_if_fail(IS_WEBKIT_CHAT_CONTAINER(self));
271 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(self);
272
273 auto loaded_library = g_list_first(priv->js_libs_to_load);
274
275 GError *error = NULL;
276 WebKitJavascriptResult* js_result = webkit_web_view_run_javascript_from_gresource_finish(webview_chat, result, &error);
277 if (!js_result) {
278 g_warning("Error loading %s: %s", (const gchar*) loaded_library->data, error->message);
279 g_error_free(error);
280 g_object_unref(self);
281 /* Stop loading view, most likely resulting in a blank page */
282 return;
283 }
284 webkit_javascript_result_unref(js_result);
285
286 priv->js_libs_to_load = g_list_remove(priv->js_libs_to_load, loaded_library->data);
287
288 if(g_list_length(priv->js_libs_to_load) > 0)
289 {
290 /* keep loading... */
291 webkit_web_view_run_javascript_from_gresource(
292 webview_chat,
293 (const gchar*) g_list_first(priv->js_libs_to_load)->data,
294 NULL,
295 (GAsyncReadyCallback) javascript_library_loaded,
296 self
297 );
298 }
299 else
300 {
301 priv->js_libs_loaded = TRUE;
302 g_signal_emit(G_OBJECT(self), webkit_chat_container_signals[READY], 0);
303
304 /* The view could now be deleted without causing a crash */
305 g_object_unref(self);
306 }
307}
308
309static void
310load_javascript_libs(WebKitWebView *webview_chat,
311 WebKitChatContainer* self)
312{
313 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(self);
314
315 /* Create the list of libraries to load */
aviau039001d2016-09-29 16:39:05 -0400316 priv->js_libs_to_load = g_list_append(priv->js_libs_to_load, (gchar*) "/cx/ring/RingGnome/linkify.js");
317 priv->js_libs_to_load = g_list_append(priv->js_libs_to_load, (gchar*) "/cx/ring/RingGnome/linkify-string.js");
318 priv->js_libs_to_load = g_list_append(priv->js_libs_to_load, (gchar*) "/cx/ring/RingGnome/linkify-html.js");
aviau039001d2016-09-29 16:39:05 -0400319
320 /* ref the chat view so that its not destroyed while we load
321 * we will unref in javascript_library_loaded
322 */
323 g_object_ref(self);
324
325 /* start loading */
326 webkit_web_view_run_javascript_from_gresource(
327 WEBKIT_WEB_VIEW(webview_chat),
328 (const gchar*) g_list_first(priv->js_libs_to_load)->data,
329 NULL,
330 (GAsyncReadyCallback) javascript_library_loaded,
331 self
332 );
333}
334
335static void
336webview_chat_load_changed(WebKitWebView *webview_chat,
337 WebKitLoadEvent load_event,
338 WebKitChatContainer* self)
339{
340 switch (load_event) {
341 case WEBKIT_LOAD_REDIRECTED:
342 {
343 g_warning("webview_chat load is being redirected, this should not happen");
344 }
345 case WEBKIT_LOAD_STARTED:
346 case WEBKIT_LOAD_COMMITTED:
347 {
348 break;
349 }
350 case WEBKIT_LOAD_FINISHED:
351 {
352 load_javascript_libs(webview_chat, self);
353 //TODO: disconnect? It shouldn't happen more than once
354 break;
355 }
356 }
357}
358
359static void
360build_view(WebKitChatContainer *view)
361{
362 g_return_if_fail(IS_WEBKIT_CHAT_CONTAINER(view));
363 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
364
aviau039001d2016-09-29 16:39:05 -0400365 priv->chatview_debug = FALSE;
366 auto ring_chatview_debug = g_getenv("RING_CHATVIEW_DEBUG");
367 if (ring_chatview_debug || g_strcmp0(ring_chatview_debug, "true") == 0)
368 {
369 priv->chatview_debug = TRUE;
370 }
371
aviau32b8dd62016-11-02 00:36:57 -0400372 /* Prepare WebKitUserContentManager */
373 WebKitUserContentManager* webkit_content_manager = webkit_user_content_manager_new();
374
375 WebKitUserStyleSheet* chatview_style_sheet = webkit_user_style_sheet_new(
376 (gchar*) g_bytes_get_data(
377 g_resources_lookup_data(
378 "/cx/ring/RingGnome/chatview.css",
379 G_RESOURCE_LOOKUP_FLAGS_NONE,
380 NULL
381 ),
382 NULL
383 ),
384 WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
385 WEBKIT_USER_STYLE_LEVEL_USER,
386 NULL,
387 NULL
388 );
389 webkit_user_content_manager_add_style_sheet(webkit_content_manager, chatview_style_sheet);
390
391 /* Prepare WebKitSettings */
aviau039001d2016-09-29 16:39:05 -0400392 WebKitSettings* webkit_settings = webkit_settings_new_with_settings(
393 "enable-javascript", TRUE,
394 "enable-developer-extras", priv->chatview_debug,
395 "enable-java", FALSE,
396 "enable-plugins", FALSE,
397 "enable-site-specific-quirks", FALSE,
398 "enable-smooth-scrolling", TRUE,
399 NULL
400 );
aviau32b8dd62016-11-02 00:36:57 -0400401
402 /* Create the WebKitWebView */
403 priv->webview_chat = GTK_WIDGET(
404 webkit_web_view_new_with_user_content_manager(
405 webkit_content_manager
406 )
407 );
408
409 gtk_container_add(GTK_CONTAINER(priv->box_webview_chat), priv->webview_chat);
410 gtk_widget_show(priv->webview_chat);
411 gtk_widget_set_vexpand(GTK_WIDGET(priv->webview_chat), TRUE);
412 gtk_widget_set_hexpand(GTK_WIDGET(priv->webview_chat), TRUE);
413
414 /* Set the WebKitSettings */
aviau039001d2016-09-29 16:39:05 -0400415 webkit_web_view_set_settings(WEBKIT_WEB_VIEW(priv->webview_chat), webkit_settings);
416
Sébastien Blinc5e68372017-07-26 12:48:01 -0400417 gtk_drag_dest_unset(priv->webview_chat); // remove drag and drop to prevent unwanted reloading
aviau039001d2016-09-29 16:39:05 -0400418 g_signal_connect(priv->webview_chat, "load-changed", G_CALLBACK(webview_chat_load_changed), view);
419 g_signal_connect_swapped(priv->webview_chat, "context-menu", G_CALLBACK(webview_chat_context_menu), view);
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400420 g_signal_connect_swapped(priv->webview_chat, "script-dialog", G_CALLBACK(webview_script_dialog), view);
Stepan Salenikovichb52dbc52016-12-27 14:05:39 -0500421#if WEBKIT_CHECK_VERSION(2, 6, 0)
aviau039001d2016-09-29 16:39:05 -0400422 g_signal_connect(priv->webview_chat, "decide-policy", G_CALLBACK(webview_chat_decide_policy), view);
423#endif
424
425 GBytes* chatview_bytes = g_resources_lookup_data(
426 "/cx/ring/RingGnome/chatview.html",
427 G_RESOURCE_LOOKUP_FLAGS_NONE,
428 NULL
429 );
430
431 webkit_web_view_load_html(
432 WEBKIT_WEB_VIEW(priv->webview_chat),
433 (gchar*) g_bytes_get_data(chatview_bytes, NULL),
434 NULL
435 );
436
437 /* Now we wait for the load-changed event, before we
438 * start loading javascript libraries */
Stepan Salenikovich1cf35e52017-05-03 16:12:11 -0400439
440 /* handle web view crash */
441 g_signal_connect_swapped(priv->webview_chat, "web-process-crashed", G_CALLBACK(webview_crashed), view);
442}
443
444static gboolean
445webview_crashed(WebKitChatContainer *self)
446{
447 g_warning("Gtk Web Process crashed! Re-createing web view");
448
449 auto priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(self);
450
451 /* make sure we destroy previous WebView */
452 if (priv->webview_chat) {
453 gtk_widget_destroy(priv->webview_chat);
454 priv->webview_chat = nullptr;
455 }
456
457 build_view(self);
458
459 return G_SOURCE_CONTINUE;
aviau039001d2016-09-29 16:39:05 -0400460}
461
462GtkWidget *
463webkit_chat_container_new()
464{
465 gpointer view = g_object_new(WEBKIT_CHAT_CONTAINER_TYPE, NULL);
466
467 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
468 priv->js_libs_loaded = FALSE;
469
470 build_view(WEBKIT_CHAT_CONTAINER(view));
471
472 return (GtkWidget *)view;
473}
474
475void
Sébastien Blin70dc0b72017-07-31 16:24:41 -0400476webkit_chat_container_set_display_links(WebKitChatContainer *view, bool display)
477{
478 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
479 gchar* function_call = g_strdup_printf("ring.chatview.setDisplayLinks(%s);",
480 display ? "true" : "false");
481
482 webkit_web_view_run_javascript(
483 WEBKIT_WEB_VIEW(priv->webview_chat),
484 function_call,
485 NULL,
486 NULL,
487 NULL
488 );
489}
490
491void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400492webkit_chat_disable_send_interaction(WebKitChatContainer *view, bool isDisabled)
493{
494 auto priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
495 gchar* function_call = g_strdup_printf("ring.chatview.disableSendMessage(%s);", isDisabled ? "true" : "false");
496
497 webkit_web_view_run_javascript(
498 WEBKIT_WEB_VIEW(priv->webview_chat),
499 function_call,
500 NULL,
501 NULL,
502 NULL
503 );
504}
505
506
507void
aviaufc213552016-11-01 12:39:39 -0400508webkit_chat_container_clear_sender_images(WebKitChatContainer *view)
509{
510 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
511
512 webkit_web_view_run_javascript(
513 WEBKIT_WEB_VIEW(priv->webview_chat),
514 "ring.chatview.clearSenderImages()",
515 NULL,
516 NULL,
517 NULL
518 );
519}
520
521void
aviau039001d2016-09-29 16:39:05 -0400522webkit_chat_container_clear(WebKitChatContainer *view)
523{
524 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
525
526 webkit_web_view_run_javascript(
527 WEBKIT_WEB_VIEW(priv->webview_chat),
528 "ring.chatview.clearMessages()",
529 NULL,
530 NULL,
531 NULL
532 );
533
aviaufc213552016-11-01 12:39:39 -0400534 webkit_chat_container_clear_sender_images(view);
aviau039001d2016-09-29 16:39:05 -0400535}
536
537void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400538webkit_chat_container_update_interaction(WebKitChatContainer *view,
539 uint64_t msgId,
540 const lrc::api::interaction::Info& interaction)
aviau039001d2016-09-29 16:39:05 -0400541{
542 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
543
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400544 auto interaction_object = interaction_to_json_interaction_object(msgId, interaction).toUtf8();
545 gchar* function_call = g_strdup_printf("ring.chatview.updateMessage(%s);", interaction_object.constData());
aviau039001d2016-09-29 16:39:05 -0400546 webkit_web_view_run_javascript(
547 WEBKIT_WEB_VIEW(priv->webview_chat),
548 function_call,
549 NULL,
550 NULL,
551 NULL
552 );
553 g_free(function_call);
554}
555
556void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400557webkit_chat_container_print_new_interaction(WebKitChatContainer *view,
558 uint64_t msgId,
559 const lrc::api::interaction::Info& interaction)
aviau039001d2016-09-29 16:39:05 -0400560{
561 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
562
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400563 auto interaction_object = interaction_to_json_interaction_object(msgId, interaction).toUtf8();
564 gchar* function_call = g_strdup_printf("ring.chatview.addMessage(%s);", interaction_object.constData());
aviau039001d2016-09-29 16:39:05 -0400565 webkit_web_view_run_javascript(
566 WEBKIT_WEB_VIEW(priv->webview_chat),
567 function_call,
568 NULL,
569 NULL,
570 NULL
571 );
572 g_free(function_call);
573}
574
575void
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400576webkit_chat_container_set_temporary(WebKitChatContainer *view, bool temporary)
aviau039001d2016-09-29 16:39:05 -0400577{
578 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
579
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400580 gchar* function_call = g_strdup_printf("ring.chatview.setTemporary(%s)", temporary ? "true" : "false");
581 webkit_web_view_run_javascript(
582 WEBKIT_WEB_VIEW(priv->webview_chat),
583 function_call,
584 NULL,
585 NULL,
586 NULL
587 );
588 g_free(function_call);
589}
590
591void
592webkit_chat_container_set_invitation(WebKitChatContainer *view, bool show,
593 const std::string& contactUri)
594{
595 auto priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
596 gchar* function_call = nullptr;
597
598 if (show) {
599 function_call = g_strdup_printf("ring.chatview.showInvitation('%s')",
600 contactUri.c_str());
601 } else {
602 function_call = g_strdup_printf("ring.chatview.hideInvitation()");
aviaufc213552016-11-01 12:39:39 -0400603 }
604
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400605 webkit_web_view_run_javascript(
606 WEBKIT_WEB_VIEW(priv->webview_chat),
607 function_call,
608 NULL,
609 NULL,
610 NULL
611 );
612 g_free(function_call);
613}
614
615void
616webkit_chat_container_set_sender_image(WebKitChatContainer *view, const std::string& sender, const std::string& senderImage)
617{
618 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
aviau039001d2016-09-29 16:39:05 -0400619
620 QJsonObject set_sender_image_object = QJsonObject();
Sébastien Blin55bff9d2017-10-03 15:15:23 -0400621 set_sender_image_object.insert("sender_contact_method", QJsonValue(QString(sender.c_str())));
622 set_sender_image_object.insert("sender_image", QJsonValue(QString(senderImage.c_str())));
aviau039001d2016-09-29 16:39:05 -0400623
Stepan Salenikovich407dc412016-11-29 11:01:31 -0500624 auto set_sender_image_object_string = QString(QJsonDocument(set_sender_image_object).toJson(QJsonDocument::Compact));
aviau039001d2016-09-29 16:39:05 -0400625
Stepan Salenikovich407dc412016-11-29 11:01:31 -0500626 gchar* function_call = g_strdup_printf("ring.chatview.setSenderImage(%s);", set_sender_image_object_string.toUtf8().constData());
aviau039001d2016-09-29 16:39:05 -0400627 webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(priv->webview_chat), function_call, NULL, NULL, NULL);
628 g_free(function_call);
629}
630
631gboolean
632webkit_chat_container_is_ready(WebKitChatContainer *view)
633{
634 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
635 return priv->js_libs_loaded;
636}