chatview.cpp 21.1 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
    } else if (order.find("RETRY_INTERACTION:") == 0) {
        try {
            auto interactionId = std::stoull(order.substr(std::string("RETRY_INTERACTION:").size()));
            if (!priv->conversation_) return;
            (*priv->accountInfo_)->conversationModel->retryInteraction(priv->conversation_->uid, interactionId);
        } catch (...) {
            g_warning("delete interaction failed: can't find %s", order.substr(std::string("RETRY_INTERACTION:").size()).c_str());
        }
290
291
292
    }
}

293
294
295
296
297
298
static void
chat_view_init(ChatView *view)
{
    gtk_widget_init_template(GTK_WIDGET(view));

    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(view);
299
    priv->settings = g_settings_new_full(get_ring_schema(), NULL, NULL);
300
301
302
303
304
305
306
307
308
309
}

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
310
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, box_webkit_chat_container);
311
312

    chat_view_signals[NEW_MESSAGES_DISPLAYED] = g_signal_new (
313
        "new-interactions-displayed",
314
315
316
317
318
319
320
        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);
321
322
323
324
325
326
327
328
329
330

    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);
331
332
}

aviau's avatar
aviau committed
333
static void
334
print_interaction_to_buffer(ChatView* self, uint64_t interactionId, const lrc::api::interaction::Info& interaction)
aviau's avatar
aviau committed
335
336
337
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

338
    if (!priv->conversation_) return;
339
    if (interaction.status == lrc::api::interaction::Status::UNREAD)
340
        (*priv->accountInfo_)->conversationModel->setInteractionRead(priv->conversation_->uid, interactionId);
341
342

    webkit_chat_container_print_new_interaction(
aviau's avatar
aviau committed
343
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
344
        *(*priv->accountInfo_)->conversationModel,
345
346
        interactionId,
        interaction
aviau's avatar
aviau committed
347
    );
348
349
}

350
static void
351
update_interaction(ChatView* self, uint64_t interactionId, const lrc::api::interaction::Info& interaction)
352
353
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
354
355
    webkit_chat_container_update_interaction(
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
356
        *(*priv->accountInfo_)->conversationModel,
357
358
        interactionId,
        interaction
359
    );
360
}
361

362
363
364
365
366
367
368
369
370
371
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
    );
}

372
373
374
375
376
static void
load_participants_images(ChatView *self)
{
    g_return_if_fail(IS_CHAT_VIEW(self));
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
377

378
    // Contact
379
    if (!priv->conversation_) return;
380
    auto contactUri = priv->conversation_->participants.front();
381
    try{
382
        auto& contact = (*priv->accountInfo_)->contactModel->getContact(contactUri);
383
384
385
        if (!contact.profileInfo.avatar.empty()) {
            webkit_chat_container_set_sender_image(
                WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
386
                (*priv->accountInfo_)->contactModel->getContactProfileId(contactUri),
387
388
389
390
391
                contact.profileInfo.avatar
                );
        }
    } catch (const std::out_of_range&) {
        // ContactModel::getContact() exception
392
393
    }

394
    // For this account
395
    if (!(*priv->accountInfo_)->profileInfo.avatar.empty()) {
396
397
        webkit_chat_container_set_sender_image(
            WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
398
399
            (*priv->accountInfo_)->contactModel->getContactProfileId((*priv->accountInfo_)->profileInfo.uri),
            (*priv->accountInfo_)->profileInfo.avatar
400
        );
401
402
403
    }
}

404
static void
405
print_text_recording(ChatView *self)
406
407
408
409
{
    g_return_if_fail(IS_CHAT_VIEW(self));
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

410
    // Read interactions
411
    if (!priv->conversation_) return;
412
413
    for (const auto& it: priv->conversation_->interactions) {
        if (it.second.status == lrc::api::interaction::Status::UNREAD)
414
            (*priv->accountInfo_)->conversationModel->setInteractionRead(priv->conversation_->uid, it.first);
415
416
    }

417
418
    webkit_chat_container_print_history(
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
419
        *(*priv->accountInfo_)->conversationModel,
420
421
        priv->conversation_->interactions
    );
422

423
    QObject::disconnect(priv->new_interaction_connection);
424
425
}

aviau's avatar
aviau committed
426
427
428
429
430
431
432
433
434
435
436
437
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)
    );

438
    display_links_toggled(self);
439
440
441
442
    print_text_recording(self);
    load_participants_images(self);

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

451
    priv->update_interaction_connection = QObject::connect(
452
    &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
453
    [self, priv](const std::string& uid, uint64_t msgId, lrc::api::interaction::Info msg) {
454
        if (!priv->conversation_) return;
455
        if (uid == priv->conversation_->uid) {
456
457
458
459
            update_interaction(self, msgId, msg);
        }
    });

460
461
462
463
464
465
466
467
468
    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);
        }
    });

469
    if (!priv->conversation_) return;
470
    auto contactUri = priv->conversation_->participants.front();
471
    try {
472
        auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri);
473
474
475
476
477
478
479
480
481
482
483
484
        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
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
514
515
516
517
518
519
520
521

    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
522
523
524
525
526
527
528
529
530
531
}

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
532
    update_chatview_frame(self);
aviau's avatar
aviau committed
533

534
    priv->webkit_ready = g_signal_connect_swapped(
aviau's avatar
aviau committed
535
536
537
538
539
540
        priv->webkit_chat_container,
        "ready",
        G_CALLBACK(webkit_chat_container_ready),
        self
    );

541
    priv->webkit_send_text = g_signal_connect(priv->webkit_chat_container,
542
543
        "script-dialog",
        G_CALLBACK(webkit_chat_container_script_dialog),
544
545
        self);

aviau's avatar
aviau committed
546
547
    if (webkit_chat_container_is_ready(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)))
        webkit_chat_container_ready(self);
548
}
Stepan Salenikovich's avatar
Stepan Salenikovich committed
549
550

GtkWidget *
551
chat_view_new (WebKitChatContainer* webkit_chat_container,
552
               AccountInfoPointer const & accountInfo,
553
               lrc::api::conversation::Info* conversation)
Stepan Salenikovich's avatar
Stepan Salenikovich committed
554
555
556
{
    ChatView *self = CHAT_VIEW(g_object_new(CHAT_VIEW_TYPE, NULL));

aviau's avatar
aviau committed
557
558
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
    priv->webkit_chat_container = GTK_WIDGET(webkit_chat_container);
559
    priv->conversation_ = conversation;
560
    priv->accountInfo_ = &accountInfo;
aviau's avatar
aviau committed
561
562

    build_chat_view(self);
Stepan Salenikovich's avatar
Stepan Salenikovich committed
563
564
565
    return (GtkWidget *)self;
}

566
void
567
chat_view_update_temporary(ChatView* self, bool showAddButton, bool showInvitation)
568
{
569
    g_return_if_fail(IS_CHAT_VIEW(self));
570
571
    auto priv = CHAT_VIEW_GET_PRIVATE(self);

Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
572
    update_chatview_frame(self);
573
574
}

575
576
lrc::api::conversation::Info
chat_view_get_conversation(ChatView *self)
577
{
578
    g_return_val_if_fail(IS_CHAT_VIEW(self), lrc::api::conversation::Info());
579
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
580
    return *priv->conversation_;
581
}
582
583
584
585
586

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