blob: 04abc04766b12cfdd9f9fb3db1e41aa12c400bfd [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>
Sébastien Blin5f35e192020-08-06 15:24:57 -04004 * Author: Anthony L�onard <anthony.leonard@savoirfairelinux.com>
Sébastien Blin1f915762020-08-03 13:27:42 -04005 * 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 "conversationsadapter.h"
25
26#include "utils.h"
27
28ConversationsAdapter::ConversationsAdapter(QObject *parent)
29 : QmlAdapterBase(parent)
30{}
31
32ConversationsAdapter::~ConversationsAdapter() {}
33
34void
35ConversationsAdapter::initQmlObject()
36{
37 conversationSmartListModel_ = new SmartListModel(LRCInstance::getCurrAccId(), this);
38
ababi0b686642020-08-18 17:21:28 +020039 QMetaObject::invokeMethod(qmlObj_, "setModel",
Sébastien Blin1f915762020-08-03 13:27:42 -040040 Q_ARG(QVariant, QVariant::fromValue(conversationSmartListModel_)));
41
42 connect(&LRCInstance::behaviorController(),
43 &BehaviorController::showChatView,
44 [this](const QString &accountId, lrc::api::conversation::Info convInfo) {
45 emit showChatView(accountId, convInfo.uid);
46 });
Sébastien Blin5f35e192020-08-06 15:24:57 -040047 connect(&LRCInstance::instance(),
48 &LRCInstance::currentAccountChanged,
49 this,
50 &ConversationsAdapter::slotAccountChanged);
Sébastien Blin1f915762020-08-03 13:27:42 -040051
52 connectConversationModel();
53}
54
55void
Sébastien Blin5f35e192020-08-06 15:24:57 -040056ConversationsAdapter::slotAccountChanged()
57{
58 connectConversationModel();
59}
60
61void
Sébastien Blin1f915762020-08-03 13:27:42 -040062ConversationsAdapter::backToWelcomePage()
63{
64 deselectConversation();
65 QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage");
66}
67
68void
69ConversationsAdapter::selectConversation(const QString &accountId,
70 const QString &convUid,
71 bool preventSendingSignal)
72{
ababi0b686642020-08-18 17:21:28 +020073 auto &accInfo = LRCInstance::getAccountInfo(accountId);
74 const auto convInfo = accInfo.conversationModel->getConversationForUID(convUid);
75
76 selectConversation(convInfo, preventSendingSignal);
Sébastien Blin1f915762020-08-03 13:27:42 -040077}
78
79void
ababi0b686642020-08-18 17:21:28 +020080ConversationsAdapter::selectConversation(const QString &convUid)
Sébastien Blin1f915762020-08-03 13:27:42 -040081{
ababi0b686642020-08-18 17:21:28 +020082 auto* convModel = LRCInstance::getCurrentConversationModel();
Sébastien Blin1f915762020-08-03 13:27:42 -040083 if (convModel == nullptr) {
84 return;
85 }
86
ababi0b686642020-08-18 17:21:28 +020087 const auto &conversation = convModel->getConversationForUID(convUid);
Sébastien Blin1f915762020-08-03 13:27:42 -040088
ababi0b686642020-08-18 17:21:28 +020089 if (selectConversation(conversation, false)) {
90
91 // If it is calling, show callview (can use showChatView signal, since it will be determined on qml).
Sébastien Blin1f915762020-08-03 13:27:42 -040092 if (!conversation.uid.isEmpty()
93 && LRCInstance::getCurrentCallModel()->hasCall(conversation.callId)) {
94 emit showChatView(LRCInstance::getCurrAccId(), conversation.uid);
95 }
96 }
97}
98
99bool
100ConversationsAdapter::selectConversation(const lrc::api::conversation::Info &item,
101 bool preventSendingSignal)
102{
ababi0b686642020-08-18 17:21:28 +0200103 // accInfo.conversationModel->selectConversation(item.uid) only emit ui
104 // behavior control signals, but sometimes we do not want that,
105 // preventSendingSignal boolean can help us to determine.
Sébastien Blin1f915762020-08-03 13:27:42 -0400106 if (LRCInstance::getCurrentConvUid() == item.uid) {
107 return false;
108 } else if (item.participants.size() > 0) {
109 auto &accInfo = LRCInstance::getAccountInfo(item.accountId);
110 LRCInstance::setSelectedConvId(item.uid);
111 if (!preventSendingSignal)
112 accInfo.conversationModel->selectConversation(item.uid);
113 accInfo.conversationModel->clearUnreadInteractions(item.uid);
114 return true;
115 }
116}
117
118void
119ConversationsAdapter::deselectConversation()
120{
121 if (LRCInstance::getCurrentConvUid().isEmpty()) {
122 return;
123 }
124
125 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
126
127 if (currentConversationModel == nullptr) {
128 return;
129 }
130
131 currentConversationModel->selectConversation("");
132 LRCInstance::setSelectedConvId();
133}
134
135void
136ConversationsAdapter::accountChangedSetUp(const QString &accountId)
137{
ababi0b686642020-08-18 17:21:28 +0200138 // Should be called when current account is changed.
Sébastien Blin1f915762020-08-03 13:27:42 -0400139 auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
140 currentTypeFilter_ = accountInfo.profileInfo.type;
141 LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
142 updateConversationsFilterWidget();
143
144 connectConversationModel();
145}
146
147void
148ConversationsAdapter::updateConversationsFilterWidget()
149{
ababi0b686642020-08-18 17:21:28 +0200150 // Update status of "Conversations" and "Invitations".
Sébastien Blin1f915762020-08-03 13:27:42 -0400151 auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
152 if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
153 currentTypeFilter_ = lrc::api::profile::Type::RING;
154 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
155 }
156 showConversationTabs(invites);
157}
158
159void
160ConversationsAdapter::setConversationFilter(const QString &type)
161{
ababi0b686642020-08-18 17:21:28 +0200162 // Set conversation filter according to type,
163 // type needs to be recognizable by lrc::api::profile::to_type.
Sébastien Blin1f915762020-08-03 13:27:42 -0400164 if (type.isEmpty()) {
165 if (LRCInstance::getCurrentAccountInfo().profileInfo.type == lrc::api::profile::Type::RING)
166 setConversationFilter(lrc::api::profile::Type::RING);
167 else
168 setConversationFilter(lrc::api::profile::Type::SIP);
169 } else {
170 setConversationFilter(lrc::api::profile::to_type(type));
171 }
172}
173
174void
175ConversationsAdapter::setConversationFilter(lrc::api::profile::Type filter)
176{
177 if (currentTypeFilter_ == filter) {
178 return;
179 }
180 currentTypeFilter_ = filter;
181 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
182}
183
184bool
185ConversationsAdapter::connectConversationModel()
186{
ababi0b686642020-08-18 17:21:28 +0200187 // Signal connections
188 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400189
190 QObject::disconnect(modelSortedConnection_);
191 QObject::disconnect(modelUpdatedConnection_);
192 QObject::disconnect(filterChangedConnection_);
193 QObject::disconnect(newConversationConnection_);
194 QObject::disconnect(conversationRemovedConnection_);
195 QObject::disconnect(conversationClearedConnection);
196 QObject::disconnect(newInteractionConnection_);
197 QObject::disconnect(interactionRemovedConnection_);
ababi0b686642020-08-18 17:21:28 +0200198 QObject::disconnect(searchStatusChangedConnection_);
199 QObject::disconnect(searchResultUpdatedConnection_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400200
ababi0b686642020-08-18 17:21:28 +0200201 modelSortedConnection_ = QObject::connect(currentConversationModel,
202 &lrc::api::ConversationModel::modelSorted,
203 [this]() {
204 conversationSmartListModel_->fillConversationsList();
205 updateConversationsFilterWidget();
206 QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
207 auto* convModel = LRCInstance::getCurrentConversationModel();
208 const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
Sébastien Blin1f915762020-08-03 13:27:42 -0400209
ababi0b686642020-08-18 17:21:28 +0200210 if (conversation.uid.isEmpty() || conversation.participants.isEmpty()) {
211 return;
212 }
213 const auto contactURI = conversation.participants[0];
214 if (contactURI.isEmpty()
215 || convModel->owner.contactModel->getContact(contactURI).profileInfo.type
216 == lrc::api::profile::Type::TEMPORARY) {
217 return;
218 }
219 QMetaObject::invokeMethod(qmlObj_, "modelSorted", Q_ARG(QVariant, contactURI));
220 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400221
ababi0b686642020-08-18 17:21:28 +0200222 modelUpdatedConnection_ = QObject::connect(currentConversationModel,
223 &lrc::api::ConversationModel::conversationUpdated,
224 [this](const QString &convUid) {
225 conversationSmartListModel_->updateConversation(convUid);
226 updateConversationsFilterWidget();
227 QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
228 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400229
ababi0b686642020-08-18 17:21:28 +0200230 filterChangedConnection_ = QObject::connect(currentConversationModel,
231 &lrc::api::ConversationModel::filterChanged,
232 [this]() {
233 conversationSmartListModel_->fillConversationsList();
234 QMetaObject::invokeMethod(qmlObj_,
235 "updateSmartList",
236 Q_ARG(QVariant, LRCInstance::getCurrAccId()));
237 updateConversationsFilterWidget();
238 QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
239 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400240
ababi0b686642020-08-18 17:21:28 +0200241 newConversationConnection_ = QObject::connect(currentConversationModel,
242 &lrc::api::ConversationModel::newConversation,
243 [this](const QString &convUid) {
244 conversationSmartListModel_->fillConversationsList();
245 QMetaObject::invokeMethod(qmlObj_,
246 "updateSmartList",
247 Q_ARG(QVariant, LRCInstance::getCurrAccId()));
248 updateConversationForNewContact(convUid);
249 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400250
ababi0b686642020-08-18 17:21:28 +0200251 conversationRemovedConnection_ = QObject::connect(currentConversationModel,
252 &lrc::api::ConversationModel::conversationRemoved,
253 [this]() {
254 conversationSmartListModel_->fillConversationsList();
255 backToWelcomePage();
256 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400257
ababi0b686642020-08-18 17:21:28 +0200258 conversationClearedConnection = QObject::connect(currentConversationModel,
259 &lrc::api::ConversationModel::conversationCleared,
260 [this](const QString &convUid) {
261 // If currently selected, switch to welcome screen (deselecting current smartlist item ).
262 if (convUid != LRCInstance::getCurrentConvUid()) {
263 return;
264 }
265 backToWelcomePage();
266 });
267
268 newInteractionConnection_ = QObject::connect(currentConversationModel,
269 &lrc::api::ConversationModel::newInteraction,
270 [this] {
271 conversationSmartListModel_->fillConversationsList();
272 updateConversationsFilterWidget();
273 QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
274 });
275
276 searchStatusChangedConnection_ = QObject::connect(currentConversationModel,
277 &lrc::api::ConversationModel::searchStatusChanged,
278 [this](const QString &status) {
279 emit showSearchStatus(status);
280 });
281
282 searchResultUpdatedConnection_ = QObject::connect(currentConversationModel,
283 &lrc::api::ConversationModel::searchResultUpdated,
284 [this]() {
285 conversationSmartListModel_->fillConversationsList();
286 QMetaObject::invokeMethod(qmlObj_, "updateSmartList",
287 Q_ARG(QVariant, LRCInstance::getCurrAccId()));
288 QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
289 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400290
291 currentConversationModel->setFilter("");
292 return true;
293}
294
295void
296ConversationsAdapter::updateConversationForNewContact(const QString &convUid)
297{
ababi0b686642020-08-18 17:21:28 +0200298 auto* convModel = LRCInstance::getCurrentConversationModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400299 if (convModel == nullptr) {
300 return;
301 }
ababi0b686642020-08-18 17:21:28 +0200302 const auto selectedUid = LRCInstance::getCurrentConvUid();
303 const auto conversation = convModel->getConversationForUID(convUid);
304 if (!conversation.uid.isEmpty() && !conversation.participants.isEmpty()) {
Sébastien Blin1f915762020-08-03 13:27:42 -0400305 try {
ababi0b686642020-08-18 17:21:28 +0200306 const auto contact = convModel->owner.contactModel->getContact(conversation.participants[0]);
Sébastien Blin1f915762020-08-03 13:27:42 -0400307 if (!contact.profileInfo.uri.isEmpty() && contact.profileInfo.uri == selectedUid) {
308 LRCInstance::setSelectedConvId(convUid);
309 convModel->selectConversation(convUid);
310 }
311 } catch (...) {
312 return;
313 }
314 }
ababi0b686642020-08-18 17:21:28 +0200315}