From 0a946c767df83b21b2675dc2b6cc5ba2913f9f2f Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Mon, 31 May 2021 13:20:08 -0400
Subject: [PATCH] calladapter: update call selection when falling from conf to
 dialog

Gitlab: #434
Change-Id: I7ebdde85c264990804a5b017f18d511f3225477f
---
 src/calladapter.cpp | 94 +++++++++++++++++++++++++++++----------------
 src/calladapter.h   | 17 ++++----
 src/lrcinstance.cpp | 18 ---------
 src/lrcinstance.h   |  2 -
 4 files changed, 69 insertions(+), 62 deletions(-)

diff --git a/src/calladapter.cpp b/src/calladapter.cpp
index b0a6d7ef2..dcc88e23d 100644
--- a/src/calladapter.cpp
+++ b/src/calladapter.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 by Savoir-faire Linux
+ * Copyright (C) 2020-2021 by Savoir-faire Linux
  * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
  * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com>
  * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com>
@@ -80,6 +80,11 @@ CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject*
             &BehaviorController::callStatusChanged,
             this,
             QOverload<const QString&, const QString&>::of(&CallAdapter::onCallStatusChanged));
+
+    connect(lrcInstance_,
+            &LRCInstance::selectedConvUidChanged,
+            this,
+            &CallAdapter::saveConferenceSubcalls);
 }
 
 void
@@ -181,47 +186,44 @@ CallAdapter::onCallStatusChanged(const QString& callId, int code)
         case lrc::api::call::Status::TIMEOUT:
         case lrc::api::call::Status::TERMINATING: {
             lrcInstance_->renderer()->removeDistantRenderer(callId);
-            Q_EMIT lrcInstance_->conversationUpdated(convInfo.uid, accountId_);
+            const auto& convInfo = lrcInstance_->getConversationFromCallId(callId);
             if (convInfo.uid.isEmpty()) {
-                break;
+                return;
             }
-            /*
-             * If it's a conference, change the smartlist index
-             * to the next remaining participant.
-             */
-            bool forceCallOnly {false};
-            if (!convInfo.confId.isEmpty()) {
-                auto callList = lrcInstance_->getConferenceSubcalls(convInfo.confId);
-                if (callList.empty()) {
-                    auto lastConference = lrcInstance_->poplastConference(convInfo.confId);
-                    if (!lastConference.isEmpty()) {
-                        callList.append(lastConference);
-                        forceCallOnly = true;
-                    }
-                }
-                if (callList.isEmpty()) {
-                    callList = lrcInstance_->getActiveCalls();
-                    forceCallOnly = true;
-                }
-                for (const auto& callId : callList) {
-                    if (!callModel->hasCall(callId)) {
-                        continue;
-                    }
-                    auto currentCall = callModel->getCall(callId);
-                    if (currentCall.status == lrc::api::call::Status::IN_PROGRESS) {
-                        const auto& otherConv = lrcInstance_->getConversationFromCallId(callId);
+
+            const auto& currentConvId = lrcInstance_->get_selectedConvUid();
+            const auto& currentConvInfo = lrcInstance_->getConversationFromConvUid(currentConvId);
+
+            // was it a conference and now is a dialog?
+            if (currentConvInfo.confId.isEmpty() && currentConfSubcalls_.size() == 2) {
+                auto it = std::find_if(currentConfSubcalls_.cbegin(),
+                                       currentConfSubcalls_.cend(),
+                                       [&callId](const QString& cid) { return cid != callId; });
+                if (it != currentConfSubcalls_.cend()) {
+                    // select the conversation using the other callId
+                    auto otherCall = lrcInstance_->getCurrentCallModel()->getCall(*it);
+                    if (otherCall.status == lrc::api::call::Status::IN_PROGRESS) {
+                        const auto& otherConv = lrcInstance_->getConversationFromCallId(*it);
                         if (!otherConv.uid.isEmpty() && otherConv.uid != convInfo.uid) {
-                            /*
-                             * Reset the call view corresponding accountId, uid.
-                             */
                             lrcInstance_->selectConversation(otherConv.uid);
-                            updateCall(otherConv.uid, otherConv.accountId, forceCallOnly);
+                            Q_EMIT lrcInstance_->conversationUpdated(otherConv.uid, accountId_);
+                            updateCall(otherConv.uid);
                         }
                     }
+                    // then clear the list
+                    currentConfSubcalls_.clear();
+                    return;
                 }
-
+            } else {
+                // okay, still a conference, so just update the subcall list and this call
+                saveConferenceSubcalls();
+                Q_EMIT lrcInstance_->conversationUpdated(currentConvInfo.uid, accountId_);
+                updateCall(currentConvInfo.uid);
                 return;
             }
+
+            Q_EMIT lrcInstance_->conversationUpdated(convInfo.uid, accountId_);
+            updateCall(currentConvInfo.uid);
             preventScreenSaver(false);
             break;
         }
@@ -231,12 +233,14 @@ CallAdapter::onCallStatusChanged(const QString& callId, int code)
             if (!convInfo.uid.isEmpty() && convInfo.uid == lrcInstance_->get_selectedConvUid()) {
                 accInfo.conversationModel->selectConversation(convInfo.uid);
             }
+            saveConferenceSubcalls();
             updateCall(convInfo.uid, accountId_);
             preventScreenSaver(true);
             break;
         }
         case lrc::api::call::Status::PAUSED:
             updateCall();
+            break;
         default:
             break;
         }
@@ -256,6 +260,14 @@ CallAdapter::onRemoteRecordingChanged(const QString& callId,
         updateRecordingPeers();
 }
 
+void
+CallAdapter::onCallAddedToConference(const QString& callId, const QString& confId)
+{
+    Q_UNUSED(callId)
+    Q_UNUSED(confId)
+    saveConferenceSubcalls();
+}
+
 void
 CallAdapter::placeAudioOnlyCall()
 {
@@ -573,6 +585,12 @@ CallAdapter::connectCallModel(const QString& accountId)
             this,
             &CallAdapter::onRemoteRecordingChanged,
             Qt::UniqueConnection);
+
+    connect(accInfo.callModel.get(),
+            &NewCallModel::callAddedToConference,
+            this,
+            &CallAdapter::onCallAddedToConference,
+            Qt::UniqueConnection);
 }
 
 void
@@ -647,6 +665,16 @@ CallAdapter::updateCallOverlay(const lrc::api::conversation::Info& convInfo)
                          bestName);
 }
 
+void
+CallAdapter::saveConferenceSubcalls()
+{
+    const auto& currentConvId = lrcInstance_->get_selectedConvUid();
+    const auto& convInfo = lrcInstance_->getConversationFromConvUid(currentConvId);
+    if (!convInfo.confId.isEmpty()) {
+        currentConfSubcalls_ = lrcInstance_->getConferenceSubcalls(convInfo.confId);
+    }
+}
+
 void
 CallAdapter::hangUpCall(const QString& callId)
 {
diff --git a/src/calladapter.h b/src/calladapter.h
index 2b181b7f0..4d76fab92 100644
--- a/src/calladapter.h
+++ b/src/calladapter.h
@@ -1,7 +1,8 @@
-/*!
- * Copyright (C) 2020 by Savoir-faire Linux
+/*
+ * Copyright (C) 2020-2021 by Savoir-faire Linux
  * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
  * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
  *
  * 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
@@ -110,24 +111,22 @@ public Q_SLOTS:
     void onParticipantsChanged(const QString& confId);
     void onCallStatusChanged(const QString& callId, int code);
     void onRemoteRecordingChanged(const QString& callId, const QSet<QString>& peerRec, bool state);
+    void onCallAddedToConference(const QString& callId, const QString& confId);
 
 private:
     void updateRecordingPeers(bool eraseLabelOnEmpty = false);
     bool shouldShowPreview(bool force);
     void showNotification(const QString& accountId, const QString& convUid);
     QJsonObject fillParticipantData(QMap<QString, QString> participant);
+    void preventScreenSaver(bool state);
+    void updateCallOverlay(const lrc::api::conversation::Info& convInfo);
+    void saveConferenceSubcalls();
 
-    // Current conf/call info.
     QString accountId_;
     QString convUid_;
 
-    // For Call Overlay
-    void updateCallOverlay(const lrc::api::conversation::Info& convInfo);
     ScreenSaver screenSaver;
-
-    void preventScreenSaver(bool state);
-
     SystemTray* systemTray_;
-
     QScopedPointer<CallOverlayModel> overlayModel_;
+    VectorString currentConfSubcalls_;
 };
diff --git a/src/lrcinstance.cpp b/src/lrcinstance.cpp
index 5c7d2cb4b..bf4caccf0 100644
--- a/src/lrcinstance.cpp
+++ b/src/lrcinstance.cpp
@@ -413,24 +413,6 @@ LRCInstance::setContentDraft(const QString& convUid,
     Q_EMIT draftSaved(convUid);
 }
 
-void
-LRCInstance::pushlastConference(const QString& confId, const QString& callId)
-{
-    lastConferences_[confId] = callId;
-}
-
-QString
-LRCInstance::poplastConference(const QString& confId)
-{
-    QString callId = {};
-    auto iter = lastConferences_.find(confId);
-    if (iter != lastConferences_.end()) {
-        callId = iter.value();
-        lastConferences_.erase(iter);
-    }
-    return callId;
-}
-
 void
 LRCInstance::selectConversation(const QString& convId, const QString& accountId)
 {
diff --git a/src/lrcinstance.h b/src/lrcinstance.h
index ff8402c32..ae8fb4ed8 100644
--- a/src/lrcinstance.h
+++ b/src/lrcinstance.h
@@ -123,8 +123,6 @@ public:
     void monitor(bool continous);
 
     bool hasActiveCall(bool withVideo = false);
-    void pushlastConference(const QString& confId, const QString& callId);
-    QString poplastConference(const QString& confId);
     VectorString getConferenceSubcalls(const QString& callId);
 
 Q_SIGNALS:
-- 
GitLab