chatview.cpp 21.2 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>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 *  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"

25
26
// std
#include <algorithm>
27

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

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

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

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

struct _ChatViewClass
{
    GtkBoxClass parent_class;
};

typedef struct _ChatViewPrivate ChatViewPrivate;

struct _ChatViewPrivate
{
aviau's avatar
aviau committed
53
54
    GtkWidget *box_webkit_chat_container;
    GtkWidget *webkit_chat_container;
Stepan Salenikovich's avatar
Stepan Salenikovich committed
55
56
    GtkWidget *hbox_chat_info;
    GtkWidget *label_peer;
57
    GtkWidget *label_cm;
58
    GtkWidget *button_close_chatview;
59
    GtkWidget *button_placecall;
60
    GtkWidget *button_add_to_conversations;
61
    GtkWidget *button_place_audio_call;
Stepan Salenikovich's avatar
Stepan Salenikovich committed
62

63
64
    GSettings *settings;

65
66
67
    lrc::api::conversation::Info* conversation_;
    AccountContainer* accountContainer_;
    bool isTemporary_;
68

69
70
71
    QMetaObject::Connection new_interaction_connection;
    QMetaObject::Connection update_interaction_connection;
    QMetaObject::Connection update_add_to_conversations;
72
73

    gulong webkit_ready;
74
    gulong webkit_send_text;
75
76
77
78
79
80
81
82
};

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,
83
    HIDE_VIEW_CLICKED,
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    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);

98
99
100
    QObject::disconnect(priv->new_interaction_connection);
    QObject::disconnect(priv->update_interaction_connection);
    QObject::disconnect(priv->update_add_to_conversations);
aviau's avatar
aviau committed
101
102
103
104

    /* 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) {
105
106
107
        /* disconnect for webkit signals */
        g_signal_handler_disconnect(priv->webkit_chat_container, priv->webkit_ready);
        priv->webkit_ready = 0;
108
109
        g_signal_handler_disconnect(priv->webkit_chat_container, priv->webkit_send_text);
        priv->webkit_send_text = 0;
110

aviau's avatar
aviau committed
111
112
113
114
115
116
        gtk_container_remove(
            GTK_CONTAINER(priv->box_webkit_chat_container),
            GTK_WIDGET(priv->webkit_chat_container)
        );
        priv->webkit_chat_container = nullptr;
    }
117
118
119
120

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

121
122
123
124
125
126
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);
}

127
128
129
130
131
132
133
134
135
136
137
138
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")
        );
    }
}

139
140
141
142
static void
placecall_clicked(ChatView *self)
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
143
    if (!priv->conversation_) return;
144
    priv->accountContainer_->info.conversationModel->placeCall(priv->conversation_->uid);
145
146
}

147
148
149
150
151
152
153
154
155
156
157
static void
place_audio_call_clicked(ChatView *self)
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);

    if (!priv->conversation_)
        return;

    priv->accountContainer_->info.conversationModel->placeAudioOnlyCall(priv->conversation_->uid);
}

158
static void
159
button_add_to_conversations_clicked(ChatView *self)
160
161
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
162
    if (!priv->conversation_) return;
163
    priv->accountContainer_->info.conversationModel->makePermanent(priv->conversation_->uid);
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
189
190
191
192
193
static gchar*
file_to_manipulate(GtkWindow* top_window, bool send)
{
    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;
}

194
static void
195
webkit_chat_container_script_dialog(G_GNUC_UNUSED GtkWidget* webview, gchar *interaction, ChatView* self)
196
{
197
198
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
    auto order = std::string(interaction);
199
    if (!priv->conversation_) return;
200
201
202
203
204
205
206
207
208
209
    if (order == "ACCEPT") {
        priv->accountContainer_->info.conversationModel->makePermanent(priv->conversation_->uid);
    } else if (order == "REFUSE") {
        priv->accountContainer_->info.conversationModel->removeConversation(priv->conversation_->uid);
    } else if (order == "BLOCK") {
        priv->accountContainer_->info.conversationModel->removeConversation(priv->conversation_->uid, true);
    } else if (order.find("SEND:") == 0) {
        // Get text body
        auto toSend = order.substr(std::string("SEND:").size());
        priv->accountContainer_->info.conversationModel->sendMessage(priv->conversation_->uid, toSend);
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
    } else if (order.find("SEND_FILE") == 0) {
        if (auto model = priv->accountContainer_->info.conversationModel.get()) {
            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) {
        if (auto model = priv->accountContainer_->info.conversationModel.get()) {
            try {
                auto interactionId = std::stoull(order.substr(std::string("ACCEPT_FILE:").size()));
                if (auto filename = file_to_manipulate(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(self))), false))
                    model->acceptTransfer(priv->conversation_->uid, interactionId, filename);
                else
                    model->cancelTransfer(priv->conversation_->uid, interactionId);
            } catch (...) {
                // ignore
            }
        }
    } else if (order.find("REFUSE_FILE:") == 0) {
        if (auto model = priv->accountContainer_->info.conversationModel.get()) {
            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);
        }
246
247
248
    }
}

249
250
251
252
253
254
static void
chat_view_init(ChatView *view)
{
    gtk_widget_init_template(GTK_WIDGET(view));

    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(view);
255
    priv->settings = g_settings_new_full(get_ring_schema(), NULL, NULL);
256

257
    g_signal_connect(priv->button_close_chatview, "clicked", G_CALLBACK(hide_chat_view), view);
258
    g_signal_connect_swapped(priv->button_placecall, "clicked", G_CALLBACK(placecall_clicked), view);
259
    g_signal_connect_swapped(priv->button_add_to_conversations, "clicked", G_CALLBACK(button_add_to_conversations_clicked), view);
260
    g_signal_connect_swapped(priv->button_place_audio_call, "clicked", G_CALLBACK(place_audio_call_clicked), view);
261
262
263
264
265
266
267
268
269
270
}

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
271
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, box_webkit_chat_container);
Stepan Salenikovich's avatar
Stepan Salenikovich committed
272
273
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, hbox_chat_info);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, label_peer);
274
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, label_cm);
275
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, button_close_chatview);
276
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, button_placecall);
277
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, button_add_to_conversations);
278
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, button_place_audio_call);
279
280

    chat_view_signals[NEW_MESSAGES_DISPLAYED] = g_signal_new (
281
        "new-interactions-displayed",
282
283
284
285
286
287
288
        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);
289
290
291
292
293
294
295
296
297
298

    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);
299
300
}

aviau's avatar
aviau committed
301
static void
302
print_interaction_to_buffer(ChatView* self, uint64_t interactionId, const lrc::api::interaction::Info& interaction)
aviau's avatar
aviau committed
303
304
305
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

306
    if (!priv->conversation_) return;
307
308
309
310
    if (interaction.status == lrc::api::interaction::Status::UNREAD)
        priv->accountContainer_->info.conversationModel->setInteractionRead(priv->conversation_->uid, interactionId);

    webkit_chat_container_print_new_interaction(
aviau's avatar
aviau committed
311
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
312
        *priv->accountContainer_->info.conversationModel,
313
314
        interactionId,
        interaction
aviau's avatar
aviau committed
315
    );
316
317
}

318
static void
319
update_interaction(ChatView* self, uint64_t interactionId, const lrc::api::interaction::Info& interaction)
320
321
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
322
323
    webkit_chat_container_update_interaction(
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
324
        *priv->accountContainer_->info.conversationModel,
325
326
        interactionId,
        interaction
327
    );
328
}
329

330
331
332
333
334
static void
load_participants_images(ChatView *self)
{
    g_return_if_fail(IS_CHAT_VIEW(self));
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
335

336
    // Contact
337
    if (!priv->conversation_) return;
338
    auto contactUri = priv->conversation_->participants.front();
339
340
341
342
343
344
345
346
347
348
349
    try{
        auto& contact = priv->accountContainer_->info.contactModel->getContact(contactUri);
        if (!contact.profileInfo.avatar.empty()) {
            webkit_chat_container_set_sender_image(
                WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
                priv->accountContainer_->info.contactModel->getContactProfileId(contactUri),
                contact.profileInfo.avatar
                );
        }
    } catch (const std::out_of_range&) {
        // ContactModel::getContact() exception
350
351
    }

352
353
354
355
356
357
358
    // For this account
    if (!priv->accountContainer_->info.profileInfo.avatar.empty()) {
        webkit_chat_container_set_sender_image(
            WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
            priv->accountContainer_->info.contactModel->getContactProfileId(priv->accountContainer_->info.profileInfo.uri),
            priv->accountContainer_->info.profileInfo.avatar
        );
359
360
361
    }
}

362
static void
363
print_text_recording(ChatView *self)
364
365
366
367
{
    g_return_if_fail(IS_CHAT_VIEW(self));
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

368
    if (!priv->conversation_) return;
369
370
    webkit_chat_container_print_history(
        WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
371
        *priv->accountContainer_->info.conversationModel,
372
373
        priv->conversation_->interactions
    );
374

375
    QObject::disconnect(priv->new_interaction_connection);
376
377
}

378
static void
379
update_add_to_conversations(ChatView *self)
380
381
382
{
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);

383
    if (!priv->conversation_) return;
384
    auto participant = priv->conversation_->participants[0];
385
386
387
388
389
390
391
392
    try {
        auto contactInfo = priv->accountContainer_->info.contactModel->getContact(participant);
        if(contactInfo.profileInfo.type != lrc::api::profile::Type::TEMPORARY
           && contactInfo.profileInfo.type != lrc::api::profile::Type::PENDING)
            gtk_widget_hide(priv->button_add_to_conversations);
    } catch (const std::out_of_range&) {
        // ContactModel::getContact() exception
    }
393
394
}

Stepan Salenikovich's avatar
Stepan Salenikovich committed
395
396
397
398
399
static void
update_contact_methods(ChatView *self)
{
    g_return_if_fail(IS_CHAT_VIEW(self));
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
400
    if (!priv->conversation_) return;
401
    auto contactUri = priv->conversation_->participants.front();
402
403
404
405
406
407
408
409
410
411
412
    try {
        auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
        auto bestId = std::string(contactInfo.registeredName).empty() ? contactInfo.profileInfo.uri : contactInfo.registeredName;
        if (contactInfo.profileInfo.alias == bestId) {
            gtk_widget_hide(priv->label_cm);
        } else {
            gtk_label_set_text(GTK_LABEL(priv->label_cm), bestId.c_str());
            gtk_widget_show(priv->label_cm);
        }
    } catch (const std::out_of_range&) {
        // ContactModel::getContact() exception
413
    }
Stepan Salenikovich's avatar
Stepan Salenikovich committed
414
415
416
}

static void
417
update_name(ChatView *self)
Stepan Salenikovich's avatar
Stepan Salenikovich committed
418
{
419
    g_return_if_fail(IS_CHAT_VIEW(self));
Stepan Salenikovich's avatar
Stepan Salenikovich committed
420
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
421
    if (!priv->conversation_) return;
422
    auto contactUri = priv->conversation_->participants.front();
423
424
425
426
427
428
429
430
    try {
        auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
        auto alias = contactInfo.profileInfo.alias;
        alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end());
        gtk_label_set_text(GTK_LABEL(priv->label_peer), alias.c_str());
    } catch (const std::out_of_range&) {
        // ContactModel::getContact() exception
    }
Stepan Salenikovich's avatar
Stepan Salenikovich committed
431
432
}

aviau's avatar
aviau committed
433
434
435
436
437
438
439
440
441
442
443
444
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)
    );

445
    display_links_toggled(self);
446
447
448
449
    print_text_recording(self);
    load_participants_images(self);

    priv->new_interaction_connection = QObject::connect(
450
    &*priv->accountContainer_->info.conversationModel, &lrc::api::ConversationModel::newInteraction,
451
    [self, priv](const std::string& uid, uint64_t interactionId, lrc::api::interaction::Info interaction) {
452
        if (!priv->conversation_) return;
453
454
455
456
        if(uid == priv->conversation_->uid) {
            print_interaction_to_buffer(self, interactionId, interaction);
        }
    });
457

458
459
460
    priv->update_interaction_connection = QObject::connect(
    &*priv->accountContainer_->info.conversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
    [self, priv](const std::string& uid, uint64_t msgId, lrc::api::interaction::Info msg) {
461
        if (!priv->conversation_) return;
462
463
464
465
466
        if(uid == priv->conversation_->uid) {
            update_interaction(self, msgId, msg);
        }
    });

467
    if (!priv->conversation_) return;
468
    auto contactUri = priv->conversation_->participants.front();
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
    try {
        auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
        priv->isTemporary_ = contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY
            || contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING;
        webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
        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_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
                                             (contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING),
                                             bestName);
        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
    }
aviau's avatar
aviau committed
489
490
491
492
493
494
495
496
497
498
}

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);

499
    update_name(self);
500
    update_add_to_conversations(self);
501
    update_contact_methods(self);
aviau's avatar
aviau committed
502

503
    priv->webkit_ready = g_signal_connect_swapped(
aviau's avatar
aviau committed
504
505
506
507
508
509
        priv->webkit_chat_container,
        "ready",
        G_CALLBACK(webkit_chat_container_ready),
        self
    );

510
    priv->webkit_send_text = g_signal_connect(priv->webkit_chat_container,
511
512
        "script-dialog",
        G_CALLBACK(webkit_chat_container_script_dialog),
513
514
        self);

aviau's avatar
aviau committed
515
516
517
    if (webkit_chat_container_is_ready(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)))
        webkit_chat_container_ready(self);

518
    gtk_widget_set_visible(priv->hbox_chat_info, TRUE);
aviau's avatar
aviau committed
519

520
}
Stepan Salenikovich's avatar
Stepan Salenikovich committed
521
522

GtkWidget *
523
524
525
chat_view_new (WebKitChatContainer* webkit_chat_container,
               AccountContainer* accountContainer,
               lrc::api::conversation::Info* conversation)
Stepan Salenikovich's avatar
Stepan Salenikovich committed
526
527
528
{
    ChatView *self = CHAT_VIEW(g_object_new(CHAT_VIEW_TYPE, NULL));

aviau's avatar
aviau committed
529
530
    ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self);
    priv->webkit_chat_container = GTK_WIDGET(webkit_chat_container);
531
532
    priv->conversation_ = conversation;
    priv->accountContainer_ = accountContainer;
aviau's avatar
aviau committed
533
534

    build_chat_view(self);
Stepan Salenikovich's avatar
Stepan Salenikovich committed
535
536
537
    return (GtkWidget *)self;
}

538
539
void
chat_view_update_temporary(ChatView* self, bool newValue)
540
{
541
    g_return_if_fail(IS_CHAT_VIEW(self));
542
543
    auto priv = CHAT_VIEW_GET_PRIVATE(self);

544
545
546
547
548
    priv->isTemporary_ = newValue;
    if (!priv->isTemporary_) {
        gtk_widget_hide(priv->button_add_to_conversations);
    }
    webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_);
549
    if (!priv->conversation_) return;
550
    auto contactUri = priv->conversation_->participants.front();
551
552
553
554
555
556
557
558
559
560
561
562
563
    try {
        auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri);
        auto bestName = contactInfo.profileInfo.alias;
        if (bestName.empty())
            bestName = contactInfo.registeredName;
        if (bestName.empty())
            bestName = contactInfo.profileInfo.uri;
        webkit_chat_container_set_invitation(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
                                             newValue,
                                             bestName);
    } catch (const std::out_of_range&) {
        // ContactModel::getContact() exception
    }
564
565
}

566
567
bool
chat_view_get_temporary(ChatView *self)
568
{
569
    g_return_val_if_fail(IS_CHAT_VIEW(self), false);
570
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
571
    return priv->isTemporary_;
572
573
}

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

void
chat_view_set_header_visible(ChatView *self, gboolean visible)
{
    auto priv = CHAT_VIEW_GET_PRIVATE(self);
    gtk_widget_set_visible(priv->hbox_chat_info, visible);
}