blob: 056286e54fd721e41a496b26d1719fbbba2f28e9 [file] [log] [blame]
Sébastien Blin1f915762020-08-03 13:27:42 -04001/*
2 * Copyright (C) 2020 by Savoir-faire Linux
3 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
4 * Author: Anthony L�onard <anthony.leonard@savoirfairelinux.com>
5 * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com>
6 * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
7 * Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
8 * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include "messagesadapter.h"
25#include "webchathelpers.h"
26
27#include "utils.h"
28
29#include <QDesktopServices>
30#include <QFileInfo>
31#include <QImageReader>
32#include <QList>
33#include <QUrl>
34
35MessagesAdapter::MessagesAdapter(QObject *parent)
36 : QmlAdapterBase(parent)
37{}
38
39MessagesAdapter::~MessagesAdapter() {}
40
41void
42MessagesAdapter::initQmlObject()
43{
Sébastien Blin5f35e192020-08-06 15:24:57 -040044 connect(&LRCInstance::instance(),
45 &LRCInstance::currentAccountChanged,
46 this,
47 &MessagesAdapter::slotAccountChanged);
48 connectConversationModel();
49}
50
51void
52MessagesAdapter::slotAccountChanged()
53{
Sébastien Blin1f915762020-08-03 13:27:42 -040054 connectConversationModel();
55}
56
57void
58MessagesAdapter::setupChatView(const QString &uid)
59{
ababi0b686642020-08-18 17:21:28 +020060
61 auto* convModel = LRCInstance::getCurrentConversationModel();
62 if (convModel == nullptr) {
63 return;
64 }
65 const auto &convInfo = convModel->getConversationForUID(uid);
66 if (convInfo.uid.isEmpty() || convInfo.participants.isEmpty()) {
Sébastien Blin1f915762020-08-03 13:27:42 -040067 return;
68 }
69
70 QString contactURI = convInfo.participants.at(0);
71
72 bool isContact = false;
73 auto selectedAccountId = LRCInstance::getCurrAccId();
74 auto &accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);
75
76 lrc::api::profile::Type contactType;
77 try {
78 auto contactInfo = accountInfo.contactModel->getContact(contactURI);
79 if (contactInfo.isTrusted) {
80 isContact = true;
81 }
82 contactType = contactInfo.profileInfo.type;
83 } catch (...) {
84 }
85
86 bool shouldShowSendContactRequestBtn = !isContact
87 && contactType != lrc::api::profile::Type::SIP;
88
89 QMetaObject::invokeMethod(qmlObj_,
90 "setSendContactRequestButtonVisible",
91 Q_ARG(QVariant, shouldShowSendContactRequestBtn));
92
93 setMessagesVisibility(false);
94
95 /*
96 * Type Indicator (contact).
97 */
98 contactIsComposing(convInfo.uid, "", false);
99 connect(LRCInstance::getCurrentConversationModel(),
100 &ConversationModel::composingStatusChanged,
101 [this](const QString &uid, const QString &contactUri, bool isComposing) {
102 contactIsComposing(uid, contactUri, isComposing);
103 });
104
105 /*
106 * Draft and message content set up.
107 */
108 Utils::oneShotConnect(qmlObj_,
109 SIGNAL(sendMessageContentSaved(const QString &)),
110 this,
111 SLOT(slotSendMessageContentSaved(const QString &)));
112
113 requestSendMessageContent();
114}
115
116void
117MessagesAdapter::connectConversationModel()
118{
ababi0b686642020-08-18 17:21:28 +0200119 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400120
121 QObject::disconnect(newInteractionConnection_);
122 QObject::disconnect(interactionRemovedConnection_);
123 QObject::disconnect(interactionStatusUpdatedConnection_);
124
ababi0b686642020-08-18 17:21:28 +0200125 newInteractionConnection_ = QObject::connect(currentConversationModel,
126 &lrc::api::ConversationModel::newInteraction,
127 [this](const QString &convUid, uint64_t interactionId,
128 const lrc::api::interaction::Info &interaction) {
129 auto accountId = LRCInstance::getCurrAccId();
130 newInteraction(accountId, convUid, interactionId, interaction);
131 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400132
ababi0b686642020-08-18 17:21:28 +0200133 interactionStatusUpdatedConnection_ = QObject::connect(currentConversationModel,
134 &lrc::api::ConversationModel::interactionStatusUpdated,
135 [this](const QString &convUid, uint64_t interactionId,
136 const lrc::api::interaction::Info &interaction) {
137 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
138 currentConversationModel->clearUnreadInteractions(convUid);
139 updateInteraction(*currentConversationModel, interactionId, interaction);
140 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400141
142 interactionRemovedConnection_
143 = QObject::connect(currentConversationModel,
144 &lrc::api::ConversationModel::interactionRemoved,
145 [this](const QString &convUid, uint64_t interactionId) {
146 Q_UNUSED(convUid);
147 removeInteraction(interactionId);
148 });
149
150 currentConversationModel->setFilter("");
151}
152
153void
154MessagesAdapter::sendContactRequest()
155{
ababi0b686642020-08-18 17:21:28 +0200156 const auto convUid = LRCInstance::getCurrentConvUid();
157 if (!convUid.isEmpty()) {
158 LRCInstance::getCurrentConversationModel()->makePermanent(convUid);
Sébastien Blin1f915762020-08-03 13:27:42 -0400159 }
160}
161
162void
ababi0b686642020-08-18 17:21:28 +0200163MessagesAdapter::accountChangedSetUp(const QString &accountId)
Sébastien Blin1f915762020-08-03 13:27:42 -0400164{
ababi0b686642020-08-18 17:21:28 +0200165 Q_UNUSED(accountId)
Sébastien Blin1f915762020-08-03 13:27:42 -0400166
167 connectConversationModel();
168}
169
170void
171MessagesAdapter::updateConversationForAddedContact()
172{
ababi0b686642020-08-18 17:21:28 +0200173 auto* convModel = LRCInstance::getCurrentConversationModel();
174 const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
Sébastien Blin1f915762020-08-03 13:27:42 -0400175
176 clear();
177 setConversationProfileData(conversation);
178 printHistory(*convModel, conversation.interactions);
179}
180
181void
182MessagesAdapter::slotSendMessageContentSaved(const QString &content)
183{
184 if (!LastConvUid_.isEmpty()) {
185 LRCInstance::setContentDraft(LastConvUid_, LRCInstance::getCurrAccId(), content);
186 }
187 LastConvUid_ = LRCInstance::getCurrentConvUid();
188
189 Utils::oneShotConnect(qmlObj_, SIGNAL(messagesCleared()), this, SLOT(slotMessagesCleared()));
190
191 setInvitation(false);
192 clear();
193 auto restoredContent = LRCInstance::getContentDraft(LRCInstance::getCurrentConvUid(),
194 LRCInstance::getCurrAccId());
195 setSendMessageContent(restoredContent);
196 emit needToUpdateSmartList();
197}
198
199void
200MessagesAdapter::slotUpdateDraft(const QString &content)
201{
202 if (!LastConvUid_.isEmpty()) {
203 LRCInstance::setContentDraft(LastConvUid_, LRCInstance::getCurrAccId(), content);
204 }
205 emit needToUpdateSmartList();
206}
207
208void
209MessagesAdapter::slotMessagesCleared()
210{
ababi0b686642020-08-18 17:21:28 +0200211 auto* convModel = LRCInstance::getCurrentConversationModel();
212 const auto convInfo = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
Sébastien Blin1f915762020-08-03 13:27:42 -0400213
214 printHistory(*convModel, convInfo.interactions);
215
216 Utils::oneShotConnect(qmlObj_, SIGNAL(messagesLoaded()), this, SLOT(slotMessagesLoaded()));
217
218 setConversationProfileData(convInfo);
219}
220
221void
222MessagesAdapter::slotMessagesLoaded()
223{
224 setMessagesVisibility(true);
225}
226
227void
228MessagesAdapter::sendMessage(const QString &message)
229{
230 try {
ababi0b686642020-08-18 17:21:28 +0200231 const auto convUid = LRCInstance::getCurrentConvUid();
Sébastien Blin1f915762020-08-03 13:27:42 -0400232 LRCInstance::getCurrentConversationModel()->sendMessage(convUid, message);
233 } catch (...) {
234 qDebug() << "Exception during sendMessage:" << message;
235 }
236}
237
238void
239MessagesAdapter::sendImage(const QString &message)
240{
241 if (message.startsWith("data:image/png;base64,")) {
242 /*
243 * Img tag contains base64 data, trim "data:image/png;base64," from data.
244 */
245 QByteArray data = QByteArray::fromStdString(message.toStdString().substr(22));
246 auto img_name_hash = QString::fromStdString(
247 QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex().toStdString());
248 QString fileName = "\\img_" + img_name_hash + ".png";
249
250 QPixmap image_to_save;
251 if (!image_to_save.loadFromData(QByteArray::fromBase64(data))) {
252 qDebug().noquote() << "Errors during loadFromData"
253 << "\n";
254 }
255
256 QString path = QString(Utils::WinGetEnv("TEMP")) + fileName;
257 if (!image_to_save.save(path, "PNG")) {
258 qDebug().noquote() << "Errors during QPixmap save"
259 << "\n";
260 }
261
262 try {
263 auto convUid = LRCInstance::getCurrentConvUid();
264 LRCInstance::getCurrentConversationModel()->sendFile(convUid, path, fileName);
265 } catch (...) {
266 qDebug().noquote() << "Exception during sendFile - base64 img"
267 << "\n";
268 }
269
270 } else {
271 /*
272 * Img tag contains file paths.
273 */
274
275 QString msg(message);
276#ifdef Q_OS_WIN
277 msg = msg.replace("file:///", "");
278#else
279 msg = msg.replace("file:///", "/");
280#endif
281 QFileInfo fi(msg);
282 QString fileName = fi.fileName();
283
284 try {
285 auto convUid = LRCInstance::getCurrentConvUid();
286 LRCInstance::getCurrentConversationModel()->sendFile(convUid, msg, fileName);
287 } catch (...) {
288 qDebug().noquote() << "Exception during sendFile - image from path"
289 << "\n";
290 }
291 }
292}
293
294void
295MessagesAdapter::sendFile(const QString &message)
296{
297 QFileInfo fi(message);
298 QString fileName = fi.fileName();
299 try {
300 auto convUid = LRCInstance::getCurrentConvUid();
301 LRCInstance::getCurrentConversationModel()->sendFile(convUid, message, fileName);
302 } catch (...) {
303 qDebug() << "Exception during sendFile";
304 }
305}
306
307void
308MessagesAdapter::retryInteraction(const QString &arg)
309{
310 bool ok;
311 uint64_t interactionUid = arg.toULongLong(&ok);
312 if (ok) {
313 LRCInstance::getCurrentConversationModel()
314 ->retryInteraction(LRCInstance::getCurrentConvUid(), interactionUid);
315 } else {
316 qDebug() << "retryInteraction - invalid arg" << arg;
317 }
318}
319
320void
321MessagesAdapter::setNewMessagesContent(const QString &path)
322{
323 if (path.length() == 0)
324 return;
325 QByteArray imageFormat = QImageReader::imageFormat(path);
326
327 if (!imageFormat.isEmpty()) {
328 setMessagesImageContent(path);
329 } else {
330 setMessagesFileContent(path);
331 }
332}
333
334void
335MessagesAdapter::deleteInteraction(const QString &arg)
336{
337 bool ok;
338 uint64_t interactionUid = arg.toULongLong(&ok);
339 if (ok) {
340 LRCInstance::getCurrentConversationModel()
341 ->clearInteractionFromConversation(LRCInstance::getCurrentConvUid(), interactionUid);
342 } else {
343 qDebug() << "DeleteInteraction - invalid arg" << arg;
344 }
345}
346
347void
348MessagesAdapter::openFile(const QString &arg)
349{
350 QUrl fileUrl("file:///" + arg);
351 if (!QDesktopServices::openUrl(fileUrl)) {
352 qDebug() << "Couldn't open file: " << fileUrl;
353 }
354}
355
356void
357MessagesAdapter::acceptFile(const QString &arg)
358{
359 try {
360 auto interactionUid = arg.toLongLong();
361 auto convUid = LRCInstance::getCurrentConvUid();
362 LRCInstance::getCurrentConversationModel()->acceptTransfer(convUid, interactionUid);
363 } catch (...) {
364 qDebug() << "JS bridging - exception during acceptFile: " << arg;
365 }
366}
367
368void
369MessagesAdapter::refuseFile(const QString &arg)
370{
371 try {
372 auto interactionUid = arg.toLongLong();
ababi0b686642020-08-18 17:21:28 +0200373 const auto convUid = LRCInstance::getCurrentConvUid();
Sébastien Blin1f915762020-08-03 13:27:42 -0400374 LRCInstance::getCurrentConversationModel()->cancelTransfer(convUid, interactionUid);
375 } catch (...) {
376 qDebug() << "JS bridging - exception during refuseFile:" << arg;
377 }
378}
379
380void
381MessagesAdapter::pasteKeyDetected()
382{
383 const QMimeData *mimeData = QApplication::clipboard()->mimeData();
384
385 if (mimeData->hasImage()) {
386 /*
387 * Save temp data into base64 format.
388 */
389 QPixmap pixmap = qvariant_cast<QPixmap>(mimeData->imageData());
390 QByteArray ba;
391 QBuffer bu(&ba);
392 bu.open(QIODevice::WriteOnly);
393 pixmap.save(&bu, "PNG");
394 auto str = QString::fromLocal8Bit(ba.toBase64());
395
396 setMessagesImageContent(str, true);
397 } else if (mimeData->hasUrls()) {
398 QList<QUrl> urlList = mimeData->urls();
399 /*
400 * Extract the local paths of the files.
401 */
402 for (int i = 0; i < urlList.size(); ++i) {
403 /*
404 * Trim file:/// from url.
405 */
406 QString filePath = urlList.at(i).toString().remove(0, 8);
407 QByteArray imageFormat = QImageReader::imageFormat(filePath);
408
409 /*
410 * Check if file is qt supported image file type.
411 */
412 if (!imageFormat.isEmpty()) {
413 setMessagesImageContent(filePath);
414 } else {
415 setMessagesFileContent(filePath);
416 }
417 }
418 } else {
419 QMetaObject::invokeMethod(qmlObj_,
420 "webViewRunJavaScript",
421 Q_ARG(QVariant,
422 QStringLiteral("replaceText(`%1`)").arg(mimeData->text())));
423 }
424}
425
426void
427MessagesAdapter::onComposing(bool isComposing)
428{
429 LRCInstance::getCurrentConversationModel()->setIsComposing(LRCInstance::getCurrentConvUid(),
430 isComposing);
431}
432
433void
434MessagesAdapter::setConversationProfileData(const lrc::api::conversation::Info &convInfo)
435{
ababi0b686642020-08-18 17:21:28 +0200436 auto* convModel = LRCInstance::getCurrentConversationModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400437 auto accInfo = &LRCInstance::getCurrentAccountInfo();
ababi0b686642020-08-18 17:21:28 +0200438 const auto conv = convModel->getConversationForUID(convInfo.uid);
Sébastien Blin1f915762020-08-03 13:27:42 -0400439
ababi0b686642020-08-18 17:21:28 +0200440 if (conv.participants.isEmpty()) {
441 return;
442 }
443
444 auto contactUri = conv.participants.front();
Sébastien Blin1f915762020-08-03 13:27:42 -0400445 if (contactUri.isEmpty()) {
446 return;
447 }
448 try {
449 auto &contact = accInfo->contactModel->getContact(contactUri);
450 auto bestName = Utils::bestNameForConversation(convInfo, *convModel);
451 setInvitation(contact.profileInfo.type == lrc::api::profile::Type::PENDING,
452 bestName,
453 contactUri);
454
455 if (!contact.profileInfo.avatar.isEmpty()) {
456 setSenderImage(contactUri, contact.profileInfo.avatar);
457 } else {
458 auto avatar = Utils::conversationPhoto(convInfo.uid, *accInfo, true);
459 QByteArray ba;
460 QBuffer bu(&ba);
461 avatar.save(&bu, "PNG");
462 setSenderImage(contactUri, QString::fromLocal8Bit(ba.toBase64()));
463 }
464 } catch (...) {
465 }
466}
467
468void
469MessagesAdapter::newInteraction(const QString &accountId,
470 const QString &convUid,
471 uint64_t interactionId,
472 const interaction::Info &interaction)
473{
474 Q_UNUSED(interactionId);
475 try {
476 auto &accountInfo = LRCInstance::getAccountInfo(accountId);
477 auto &convModel = accountInfo.conversationModel;
ababi0b686642020-08-18 17:21:28 +0200478 const auto conversation = convModel->getConversationForUID(convUid);
Sébastien Blin1f915762020-08-03 13:27:42 -0400479
480 if (conversation.uid.isEmpty()) {
481 return;
482 }
483 if (!interaction.authorUri.isEmpty()
484 && (!QApplication::focusWindow() || LRCInstance::getCurrAccId() != accountId)) {
485 /*
486 * TODO: Notification from other accounts.
487 */
488 }
489 if (convUid != LRCInstance::getCurrentConvUid()) {
490 return;
491 }
492 convModel->clearUnreadInteractions(convUid);
493 printNewInteraction(*convModel, interactionId, interaction);
494 } catch (...) {
495 }
496}
497
498void
499MessagesAdapter::updateDraft()
500{
501 Utils::oneShotConnect(qmlObj_,
502 SIGNAL(sendMessageContentSaved(const QString &)),
503 this,
504 SLOT(slotUpdateDraft(const QString &)));
505
506 requestSendMessageContent();
507}
508
509/*
510 * JS invoke.
511 */
512void
513MessagesAdapter::setMessagesVisibility(bool visible)
514{
515 QString s = QString::fromLatin1(visible ? "showMessagesDiv();" : "hideMessagesDiv();");
516 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
517}
518
519void
520MessagesAdapter::requestSendMessageContent()
521{
522 QString s = QString::fromLatin1("requestSendMessageContent();");
523 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
524}
525
526void
527MessagesAdapter::setInvitation(bool show, const QString &contactUri, const QString &contactId)
528{
529 QString s
530 = show
531 ? QString::fromLatin1("showInvitation(\"%1\", \"%2\")").arg(contactUri).arg(contactId)
532 : QString::fromLatin1("showInvitation()");
533
534 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
535}
536
537void
538MessagesAdapter::clear()
539{
540 QString s = QString::fromLatin1("clearMessages();");
541 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
542}
543
544void
545MessagesAdapter::printHistory(lrc::api::ConversationModel &conversationModel,
546 const std::map<uint64_t, lrc::api::interaction::Info> interactions)
547{
548 auto interactionsStr = interactionsToJsonArrayObject(conversationModel, interactions).toUtf8();
549 QString s = QString::fromLatin1("printHistory(%1);").arg(interactionsStr.constData());
550 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
551}
552
553void
554MessagesAdapter::setSenderImage(const QString &sender, const QString &senderImage)
555{
556 QJsonObject setSenderImageObject = QJsonObject();
557 setSenderImageObject.insert("sender_contact_method", QJsonValue(sender));
558 setSenderImageObject.insert("sender_image", QJsonValue(senderImage));
559
560 auto setSenderImageObjectString = QString(
561 QJsonDocument(setSenderImageObject).toJson(QJsonDocument::Compact));
562 QString s = QString::fromLatin1("setSenderImage(%1);")
563 .arg(setSenderImageObjectString.toUtf8().constData());
564 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
565}
566
567void
568MessagesAdapter::printNewInteraction(lrc::api::ConversationModel &conversationModel,
569 uint64_t msgId,
570 const lrc::api::interaction::Info &interaction)
571{
572 auto interactionObject
573 = interactionToJsonInteractionObject(conversationModel, msgId, interaction).toUtf8();
574 if (interactionObject.isEmpty()) {
575 return;
576 }
577 QString s = QString::fromLatin1("addMessage(%1);").arg(interactionObject.constData());
578 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
579}
580
581void
582MessagesAdapter::updateInteraction(lrc::api::ConversationModel &conversationModel,
583 uint64_t msgId,
584 const lrc::api::interaction::Info &interaction)
585{
586 auto interactionObject
587 = interactionToJsonInteractionObject(conversationModel, msgId, interaction).toUtf8();
588 if (interactionObject.isEmpty()) {
589 return;
590 }
591 QString s = QString::fromLatin1("updateMessage(%1);").arg(interactionObject.constData());
592 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
593}
594
595void
596MessagesAdapter::setMessagesImageContent(const QString &path, bool isBased64)
597{
598 if (isBased64) {
599 QString param = QString("addImage_base64('file://%1')").arg(path);
600 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param));
601 } else {
602 QString param = QString("addImage_path('file://%1')").arg(path);
603 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param));
604 }
605}
606
607void
608MessagesAdapter::setMessagesFileContent(const QString &path)
609{
610 qint64 fileSize = QFileInfo(path).size();
611 QString fileName = QFileInfo(path).fileName();
612 /*
613 * If file name is too large, trim it.
614 */
615 if (fileName.length() > 15) {
616 fileName = fileName.remove(12, fileName.length() - 12) + "...";
617 }
618 QString param = QString("addFile_path('%1','%2','%3')")
619 .arg(path, fileName, Utils::humanFileSize(fileSize));
620
621 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param));
622}
623
624void
625MessagesAdapter::removeInteraction(uint64_t interactionId)
626{
627 QString s = QString::fromLatin1("removeInteraction(%1);").arg(QString::number(interactionId));
628 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
629}
630
631void
632MessagesAdapter::setSendMessageContent(const QString &content)
633{
634 QString s = QString::fromLatin1("setSendMessageContent(`%1`);").arg(content);
635 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
636}
637
638void
639MessagesAdapter::contactIsComposing(const QString &uid, const QString &contactUri, bool isComposing)
640{
641 if (LRCInstance::getCurrentConvUid() == uid) {
642 QString s
643 = QString::fromLatin1("showTypingIndicator(`%1`, %2);").arg(contactUri).arg(isComposing);
644 QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s));
645 }
646}
647
648void
649MessagesAdapter::acceptInvitation()
650{
ababi0b686642020-08-18 17:21:28 +0200651 const auto convUid = LRCInstance::getCurrentConvUid();
Sébastien Blin1f915762020-08-03 13:27:42 -0400652 LRCInstance::getCurrentConversationModel()->makePermanent(convUid);
653}
654
655void
656MessagesAdapter::refuseInvitation()
657{
658 auto convUid = LRCInstance::getCurrentConvUid();
659 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, false);
660 setInvitation(false);
661}
662
663void
664MessagesAdapter::blockConversation()
665{
666 auto convUid = LRCInstance::getCurrentConvUid();
667 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
668 setInvitation(false);
669}