chatview.cpp 20.6 KB
Newer Older
1
/*
Guillaume Roguez's avatar
Guillaume Roguez committed
2
 *  Copyright (C) 2016-2018 Savoir-faire Linux Inc.
3
 *  Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
aviau's avatar
aviau committed
4
 *  Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
5
6
 *  Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com>
 *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
7
 *  Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */

#include "chatview.h"

26
27
// std
#include <algorithm>
28

29
30
31
// GTK
#include <glib/gi18n.h>

32
33
34
35
// LRC
#include <api/contactmodel.h>
#include <api/conversationmodel.h>
#include <api/contact.h>
36

37
38
// Client
#include "utils/files.h"
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
struct _ChatView
{
    GtkBox parent;
};

struct _ChatViewClass
{
    GtkBoxClass parent_class;
};

typedef struct _ChatViewPrivate ChatViewPrivate;

struct _ChatViewPrivate
{
aviau's avatar
aviau committed
54
55
    GtkWidget *box_webkit_chat_container;
    GtkWidget *webkit_chat_container;
Stepan Salenikovich's avatar
Stepan Salenikovich committed
56

57
58
    GSettings *settings;

59
    lrc::api::conversation::Info* conversation_;
60
    AccountInfoPointer const * accountInfo_;
61

62
    QMetaObject::Connection new_interaction_connection;
63
    QMetaObject::Connection interaction_removed;
64
65
    QMetaObject::Connection update_interaction_connection;
    QMetaObject::Connection update_add_to_conversations;
66
67

    gulong webkit_ready;
68
    gulong webkit_send_text;
69
70
71
72
73
74
75
76
};

G_DEFINE_TYPE_WITH_PRIVATE(ChatView, chat_view, GTK_TYPE_BOX);

#define CHAT_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CHAT_VIEW_TYPE, ChatViewPrivate))

enum {
    NEW_MESSAGES_DISPLAYED,
77
    HIDE_VIEW_CLICKED,
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    LAST_SIGNAL
};

static guint chat_view_signals[LAST_SIGNAL] = { 0 };

static void
chat_view_dispose(GObject *object)
{
    ChatView *view;
    ChatViewPrivate *priv;

    view = CHAT_VIEW(object);
    priv = CHAT_VIEW_GET_PRIVATE(view);

92
93
    QObject::disconnect(priv->new_interaction_connection);
    QObject::disconnect(priv->update_interaction_connection);
94
    QObject::disconnect(priv->interaction_removed);
95
    QObject::disconnect(priv->update_add_to_conversations);
aviau's avatar
aviau committed
96
97
98
99

    /* Destroying the box will also destroy its children, and we wouldn't
     * want that. So we remove the webkit_chat_container from the box. */
    if (priv->webkit_chat_container) {
100
101
102
        /* disconnect for webkit signals */
        g_signal_handler_disconnect(priv->webkit_chat_container, priv->webkit_ready);
        priv->webkit_ready = 0;
103
104
        g_signal_handler_disconnect(priv->webkit_chat_container, priv->webkit_send_text);
        priv->webkit_send_text = 0;
105

aviau's avatar
aviau committed
106
107
108
109
110
111
        gtk_container_remove(
            GTK_CONTAINER(priv->box_webkit_chat_container),
            GTK_WIDGET(priv->webkit_chat_container)
        );
        priv->webkit_chat_container = nullptr;
    }
112
113
114
115

    G_OBJECT_CLASS(chat_view_parent_class)->dispose(object);
}

116
117
118
119
120
121
static void
hide_chat_view(G_GNUC_UNUSED GtkWidget *widget, ChatView *self)
{
    g_signal_emit(G_OBJECT(self), chat_view_signals[HIDE_VIEW_CLICKED], 0);
}

122
123
124
125
126
127
128
129
130
131
132
133
static void
display_links_toggled(ChatView *self)
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
    if (priv->webkit_chat_container) {
        webkit_chat_container_set_display_links(
            WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
            g_settings_get_boolean(priv->settings, "enable-display-links")
        );
    }
}

134
135
136
137
static void
placecall_clicked(ChatView *self)
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
138
    if (!priv->conversation_) return;
139
    (*priv->accountInfo_)->conversationModel->placeCall(priv->conversation_->uid);
140
141
}

142
143
144
145
146
147
148
149
static void
place_audio_call_clicked(ChatView *self)
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);

    if (!priv->conversation_)
        return;

150
    (*priv->accountInfo_)->conversationModel->placeAudioOnlyCall(priv->conversation_->uid);
151
152
}

153
static void
154
button_add_to_conversations_clicked(ChatView *self)
155
156
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
157
    if (!priv->conversation_) return;
158
    (*priv->accountInfo_)->conversationModel->makePermanent(priv->conversation_->uid);
159
160
}

161
static gchar*
162
file_to_manipulate(GtkWindow* top_window, bool send)
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
{
    GtkWidget* dialog;
    GtkFileChooserAction action = send? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE;
    gint res;
    gchar* filename = nullptr;

    dialog = gtk_file_chooser_dialog_new(send? _("Send File") : _("Save File"),
                                         top_window,
                                         action,
                                         _("_Cancel"),
                                         GTK_RESPONSE_CANCEL,
                                         send? _("_Open"): _("_Save"),
                                         GTK_RESPONSE_ACCEPT,
                                         nullptr);

    res = gtk_dialog_run (GTK_DIALOG(dialog));

    if (res == GTK_RESPONSE_ACCEPT) {
        auto chooser = GTK_FILE_CHOOSER(dialog);
        filename = gtk_file_chooser_get_filename(chooser);
    }
    gtk_widget_destroy (dialog);

    return filename;
}

Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
189
190
static void update_chatview_frame(ChatView *self);

191
static void
Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
192
webkit_chat_container_script_dialog(GtkWidget* webview, gchar *interaction, ChatView* self)
193
{
194
195
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
    auto order = std::string(interaction);
196
    if (!priv->conversation_) return;
197
    if (order == "ACCEPT") {
198
        (*priv->accountInfo_)->conversationModel->makePermanent(priv->conversation_->uid);
199
    } else if (order == "REFUSE") {
200
        (*priv->accountInfo_)->conversationModel->removeConversation(priv->conversation_->uid);
201
    } else if (order == "BLOCK") {
202
        (*priv->accountInfo_)->conversationModel->removeConversation(priv->conversation_->uid, true);
Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    } else if (order == "UNBLOCK") {
        try {
            auto contactUri = priv->conversation_->participants.front();
            auto& contact = (*priv->accountInfo_)->contactModel->getContact(contactUri);
            (*priv->accountInfo_)->contactModel->addContact(contact);
        } catch (std::out_of_range) {
            g_debug("webkit_chat_container_script_dialog: oor while retrieving invalid contact info. Chatview bug ?");
        }
    } else if (order.find("PLACE_CALL") == 0) {
        placecall_clicked(self);
    } else if (order.find("PLACE_AUDIO_CALL") == 0) {
        place_audio_call_clicked(self);
    } else if (order.find("CLOSE_CHATVIEW") == 0) {
        hide_chat_view(webview, self);
217
218
219
    } else if (order.find("SEND:") == 0) {
        // Get text body
        auto toSend = order.substr(std::string("SEND:").size());
220
        (*priv->accountInfo_)->conversationModel->sendMessage(priv->conversation_->uid, toSend);
221
    } else if (order.find("SEND_FILE") == 0) {
222
        if (auto model = (*priv->accountInfo_)->conversationModel.get()) {
223
224
225
226
            if (auto filename = file_to_manipulate(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(self))), true))
                model->sendFile(priv->conversation_->uid, filename, g_path_get_basename(filename));
        }
    } else if (order.find("ACCEPT_FILE:") == 0) {
227
        if (auto model = (*priv->accountInfo_)->conversationModel.get()) {
228
229
            try {
                auto interactionId = std::stoull(order.substr(std::string("ACCEPT_FILE:").size()));
230
231

                lrc::api::datatransfer::Info info = {};
232
                (*priv->accountInfo_)->conversationModel->getTransferInfo(interactionId, info);
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
                // get prefered directory destination.
                auto* download_directory_variant = g_settings_get_value(priv->settings, "download-folder");
                char* download_directory_value;
                g_variant_get(download_directory_variant, "&s", &download_directory_value);
                std::string default_download_dir = g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD);
                auto current_value = std::string(download_directory_value);
                if (current_value.empty()) {
                    g_settings_set_value(priv->settings, "download-folder", g_variant_new("s", default_download_dir.c_str()));
                }
                // get full path
                std::string filename = current_value.empty()? default_download_dir.c_str() : download_directory_value;
                if (!filename.empty() && filename.back() != '/') filename += "/";
                filename += info.displayName;

                model->acceptTransfer(priv->conversation_->uid, interactionId, filename);
249
250
251
252
253
            } catch (...) {
                // ignore
            }
        }
    } else if (order.find("REFUSE_FILE:") == 0) {
254
        if (auto model = (*priv->accountInfo_)->conversationModel.get()) {
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
            try {
                auto interactionId = std::stoull(order.substr(std::string("REFUSE_FILE:").size()));
                model->cancelTransfer(priv->conversation_->uid, interactionId);
            } catch (...) {
                // ignore
            }
        }
    } else if (order.find("OPEN_FILE:") == 0) {
        // Get text body
        auto filename {"file://" + order.substr(std::string("OPEN_FILE:").size())};
        filename.erase(std::find_if(filename.rbegin(), filename.rend(),
            std::not1(std::ptr_fun<int, int>(std::isspace))).base(), filename.end());
        GError* error = nullptr;
        if (!gtk_show_uri(nullptr, filename.c_str(), GDK_CURRENT_TIME, &error)) {
            g_debug("Could not open file: %s", error->message);
            g_error_free(error);
        }
Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
272
273
    } else if (order.find("ADD_TO_CONVERSATIONS") == 0) {
        button_add_to_conversations_clicked(self);
274
275
276
277
278
279
280
281
    } else if (order.find("DELETE_INTERACTION:") == 0) {
        try {
            auto interactionId = std::stoull(order.substr(std::string("DELETE_INTERACTION:").size()));
            if (!priv->conversation_) return;
            (*priv->accountInfo_)->conversationModel->clearInteractionFromConversation(priv->conversation_->uid, interactionId);
        } catch (...) {
            g_warning("delete interaction failed: can't find %s", order.substr(std::string("DELETE_INTERACTION:").size()).c_str());
        }
282
283
284
    }
}

285
286
287
288
289
290
static void
chat_view_init(ChatView *view)
{
    gtk_widget_init_template(GTK_WIDGET(view));

    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(view);
291
    priv->settings = g_settings_new_full(get_ring_schema(), NULL, NULL);
292
293
294
295
296
297
298
299
300
301
}

static void
chat_view_class_init(ChatViewClass *klass)
{
    G_OBJECT_CLASS(klass)->dispose = chat_view_dispose;

    gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
                                                "/cx/ring/RingGnome/chatview.ui");

aviau's avatar
aviau committed
302
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, box_webkit_chat_container);
303
304

    chat_view_signals[NEW_MESSAGES_DISPLAYED] = g_signal_new (
305
        "new-interactions-displayed",
306
307
308
309
310
311
312
        G_TYPE_FROM_CLASS(klass),
        (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
        0,
        nullptr,
        nullptr,
        g_cclosure_marshal_VOID__VOID,
        G_TYPE_NONE, 0);
313
314
315
316
317
318
319
320
321
322

    chat_view_signals[HIDE_VIEW_CLICKED] = g_signal_new (
        "hide-view-clicked",
        G_TYPE_FROM_CLASS(klass),
        (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
        0,
        nullptr,
        nullptr,
        g_cclosure_marshal_VOID__VOID,
        G_TYPE_NONE, 0);
323
324
}

aviau's avatar
aviau committed
325
static void
326
print_interaction_to_buffer(ChatView* self, uint64_t interactionId, const lrc::api::interaction::Info& interaction)
aviau's avatar
aviau committed
327
328
329
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

330
    if (!priv->conversation_) return;
331
    if (interaction.status == lrc::api::interaction::Status::UNREAD)
332
        (*priv->accountInfo_)->conversationModel->setInteractionRead(priv->conversation_->uid, interactionId);
333
334

    webkit_chat_container_print_new_interaction(
aviau's avatar
aviau committed
335
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
336
        *(*priv->accountInfo_)->conversationModel,
337
338
        interactionId,
        interaction
aviau's avatar
aviau committed
339
    );
340
341
}

342
static void
343
update_interaction(ChatView* self, uint64_t interactionId, const lrc::api::interaction::Info& interaction)
344
345
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
346
347
    webkit_chat_container_update_interaction(
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
348
        *(*priv->accountInfo_)->conversationModel,
349
350
        interactionId,
        interaction
351
    );
352
}
353

354
355
356
357
358
359
360
361
362
363
static void
remove_interaction(ChatView* self, uint64_t interactionId)
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
    webkit_chat_container_remove_interaction(
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
        interactionId
    );
}

364
365
366
367
368
static void
load_participants_images(ChatView *self)
{
    g_return_if_fail(IS_CHAT_VIEW(self));
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
369

370
    // Contact
371
    if (!priv->conversation_) return;
372
    auto contactUri = priv->conversation_->participants.front();
373
    try{
374
        auto& contact = (*priv->accountInfo_)->contactModel->getContact(contactUri);
375
376
377
        if (!contact.profileInfo.avatar.empty()) {
            webkit_chat_container_set_sender_image(
                WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
378
                (*priv->accountInfo_)->contactModel->getContactProfileId(contactUri),
379
380
381
382
383
                contact.profileInfo.avatar
                );
        }
    } catch (const std::out_of_range&) {
        // ContactModel::getContact() exception
384
385
    }

386
    // For this account
387
    if (!(*priv->accountInfo_)->profileInfo.avatar.empty()) {
388
389
        webkit_chat_container_set_sender_image(
            WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
390
391
            (*priv->accountInfo_)->contactModel->getContactProfileId((*priv->accountInfo_)->profileInfo.uri),
            (*priv->accountInfo_)->profileInfo.avatar
392
        );
393
394
395
    }
}

396
static void
397
print_text_recording(ChatView *self)
398
399
400
401
{
    g_return_if_fail(IS_CHAT_VIEW(self));
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

402
    // Read interactions
403
    if (!priv->conversation_) return;
404
405
    for (const auto& it: priv->conversation_->interactions) {
        if (it.second.status == lrc::api::interaction::Status::UNREAD)
406
            (*priv->accountInfo_)->conversationModel->setInteractionRead(priv->conversation_->uid, it.first);
407
408
    }

409
410
    webkit_chat_container_print_history(
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
411
        *(*priv->accountInfo_)->conversationModel,
412
413
        priv->conversation_->interactions
    );
414

415
    QObject::disconnect(priv->new_interaction_connection);
416
417
}

aviau's avatar
aviau committed
418
419
420
421
422
423
424
425
426
427
428
429
static void
webkit_chat_container_ready(ChatView* self)
{
    /* The webkit chat container has loaded the javascript libraries, we can
     * now use it. */

    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

    webkit_chat_container_clear(
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)
    );

430
    display_links_toggled(self);
431
432
433
434
    print_text_recording(self);
    load_participants_images(self);

    priv->new_interaction_connection = QObject::connect(
435
    &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::newInteraction,
436
    [self, priv](const std::string& uid, uint64_t interactionId, lrc::api::interaction::Info interaction) {
437
        if (!priv->conversation_) return;
438
        if (uid == priv->conversation_->uid) {
439
440
441
            print_interaction_to_buffer(self, interactionId, interaction);
        }
    });
442

443
    priv->update_interaction_connection = QObject::connect(
444
    &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
445
    [self, priv](const std::string& uid, uint64_t msgId, lrc::api::interaction::Info msg) {
446
        if (!priv->conversation_) return;
447
        if (uid == priv->conversation_->uid) {
448
449
450
451
            update_interaction(self, msgId, msg);
        }
    });

452
453
454
455
456
457
458
459
460
    priv->interaction_removed = QObject::connect(
    &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::interactionRemoved,
    [self, priv](const std::string& convUid, uint64_t interactionId) {
        if (!priv->conversation_) return;
        if (convUid == priv->conversation_->uid) {
            remove_interaction(self, interactionId);
        }
    });

461
    if (!priv->conversation_) return;
462
    auto contactUri = priv->conversation_->participants.front();
463
    try {
464
        auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
465
466
467
468
469
470
471
472
473
474
475
476
        auto bestName = contactInfo.profileInfo.alias;
        if (bestName.empty())
            bestName = contactInfo.registeredName;
        if (bestName.empty())
            bestName = contactInfo.profileInfo.uri;
        bestName.erase(std::remove(bestName.begin(), bestName.end(), '\r'), bestName.end());
        webkit_chat_disable_send_interaction(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
                                             (contactInfo.profileInfo.type == lrc::api::profile::Type::SIP)
                                             && priv->conversation_->callId.empty());
    } catch (const std::out_of_range&) {
        // ContactModel::getContact() exception
    }
Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513

    update_chatview_frame(self);
}

static void
update_chatview_frame(ChatView* self)
{
    g_return_if_fail(IS_CHAT_VIEW(self));
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
    if (!priv->conversation_) return;

    auto contactUri = priv->conversation_->participants.front();

    lrc::api::contact::Info contactInfo;
    try {
        contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
    } catch (const std::out_of_range&) {
        g_debug("update_chatview_frame: failed to retrieve contactInfo");
        return;
    }

    // get alias and bestName
    auto alias = contactInfo.profileInfo.alias;
    auto bestName = contactInfo.registeredName;
    if (bestName.empty())
        bestName = contactInfo.profileInfo.uri;
    bestName.erase(std::remove(bestName.begin(), bestName.end(), '\r'), bestName.end());
    alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end());

    // get temporary status
    bool temp = contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY || contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING;

    webkit_chat_update_chatview_frame(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), contactInfo.isBanned, temp, alias.c_str(), bestName.c_str());

    webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
                                             (contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING),
                                             bestName);
aviau's avatar
aviau committed
514
515
516
517
518
519
520
521
522
523
}

static void
build_chat_view(ChatView* self)
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

    gtk_container_add(GTK_CONTAINER(priv->box_webkit_chat_container), priv->webkit_chat_container);
    gtk_widget_show(priv->webkit_chat_container);

Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
524
    update_chatview_frame(self);
aviau's avatar
aviau committed
525

526
    priv->webkit_ready = g_signal_connect_swapped(
aviau's avatar
aviau committed
527
528
529
530
531
532
        priv->webkit_chat_container,
        "ready",
        G_CALLBACK(webkit_chat_container_ready),
        self
    );

533
    priv->webkit_send_text = g_signal_connect(priv->webkit_chat_container,
534
535
        "script-dialog",
        G_CALLBACK(webkit_chat_container_script_dialog),
536
537
        self);

aviau's avatar
aviau committed
538
539
    if (webkit_chat_container_is_ready(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)))
        webkit_chat_container_ready(self);
540
}
Stepan Salenikovich's avatar
Stepan Salenikovich committed
541
542

GtkWidget *
543
chat_view_new (WebKitChatContainer* webkit_chat_container,
544
               AccountInfoPointer const & accountInfo,
545
               lrc::api::conversation::Info* conversation)
Stepan Salenikovich's avatar
Stepan Salenikovich committed
546
547
548
{
    ChatView *self = CHAT_VIEW(g_object_new(CHAT_VIEW_TYPE, NULL));

aviau's avatar
aviau committed
549
550
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
    priv->webkit_chat_container = GTK_WIDGET(webkit_chat_container);
551
    priv->conversation_ = conversation;
552
    priv->accountInfo_ = &accountInfo;
aviau's avatar
aviau committed
553
554

    build_chat_view(self);
Stepan Salenikovich's avatar
Stepan Salenikovich committed
555
556
557
    return (GtkWidget *)self;
}

558
void
559
chat_view_update_temporary(ChatView* self, bool showAddButton, bool showInvitation)
560
{
561
    g_return_if_fail(IS_CHAT_VIEW(self));
562
563
    auto priv = CHAT_VIEW_GET_PRIVATE(self);

Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
564
    update_chatview_frame(self);
565
566
}

567
568
lrc::api::conversation::Info
chat_view_get_conversation(ChatView *self)
569
{
570
    g_return_val_if_fail(IS_CHAT_VIEW(self), lrc::api::conversation::Info());
571
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
572
    return *priv->conversation_;
573
}
574
575
576
577
578

void
chat_view_set_header_visible(ChatView *self, gboolean visible)
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
579
    webkit_chat_set_header_visible(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), visible);
580
}