Optimize activities fetch requests. Do not fetch when the Tray is not open. Fetch...
authoralex-z <blackslayer4@gmail.com>
Wed, 13 Apr 2022 13:35:40 +0000 (16:35 +0300)
committeralex-z <blackslayer4@gmail.com>
Fri, 29 Apr 2022 17:59:56 +0000 (20:59 +0300)
Signed-off-by: alex-z <blackslayer4@gmail.com>
src/gui/fileactivitylistmodel.cpp
src/gui/tray/activitylistmodel.cpp
src/gui/tray/activitylistmodel.h
src/gui/tray/notificationhandler.cpp
src/gui/tray/usermodel.cpp
src/gui/tray/usermodel.h

index ee7360ef22e9288582cf3a0ea4dc455010a00e9c..5fadec9816ad9055177fdb4f7600a732485ee66c 100644 (file)
@@ -43,7 +43,7 @@ void FileActivityListModel::startFetchJob()
     if (!accountState()->isConnected()) {
         return;
     }
-    setCurrentlyFetching(true);
+    setAndRefreshCurrentlyFetching(true);
 
     const QString url(QStringLiteral("ocs/v2.php/apps/activity/api/v2/activity/filter"));
     auto job = new JsonApiJob(accountState()->account(), url, this);
index d01bb1c7e804e0bc4c6cbb9ef5f5c192d6e8f576..147824582ce7b3883d9d3acd54532e7f00660db4 100644 (file)
@@ -34,6 +34,7 @@
 #include "activitydata.h"
 #include "activitylistmodel.h"
 #include "systray.h"
+#include "tray/usermodel.h"
 
 #include "theme.h"
 
@@ -95,9 +96,13 @@ void ActivityListModel::setCurrentItem(const int currentItem)
     _currentItem = currentItem;
 }
 
-void ActivityListModel::setCurrentlyFetching(bool value)
+void ActivityListModel::setAndRefreshCurrentlyFetching(bool value)
 {
+    if (_currentlyFetching == value) {
+        return;
+    }
     _currentlyFetching = value;
+    insertOrRemoveDummyFetchingActivity();
 }
 
 bool ActivityListModel::currentlyFetching() const
@@ -353,9 +358,9 @@ int ActivityListModel::rowCount(const QModelIndex &parent) const
 bool ActivityListModel::canFetchMore(const QModelIndex &) const
 {
     // We need to be connected to be able to fetch more
-    if (_accountState && _accountState->isConnected()) {
+    if (_accountState && _accountState->isConnected() && Systray::instance()->isOpen()) {
         // If the fetching is reported to be done or we are currently fetching we can't fetch more
-        if (!_doneFetching && !_currentlyFetching) {
+        if (!_doneFetching && !currentlyFetching()) {
             return true;
         }
     }
@@ -365,7 +370,7 @@ bool ActivityListModel::canFetchMore(const QModelIndex &) const
 
 void ActivityListModel::startFetchJob()
 {
-    if (!_accountState->isConnected()) {
+    if (!_accountState->isConnected() || currentlyFetching()) {
         return;
     }
     auto *job = new JsonApiJob(_accountState->account(), QLatin1String("ocs/v2.php/apps/activity/api/v2/activity"), this);
@@ -378,7 +383,7 @@ void ActivityListModel::startFetchJob()
     params.addQueryItem(QLatin1String("limit"), QString::number(50));
     job->addQueryParams(params);
 
-    _currentlyFetching = true;
+    setAndRefreshCurrentlyFetching(true);
     qCInfo(lcActivity) << "Start fetching activities for " << _accountState->account()->displayName();
     job->start();
 }
@@ -403,7 +408,7 @@ void ActivityListModel::ingestActivities(const QJsonArray &activities)
     ActivityList list;
 
     QDateTime oldestDate = QDateTime::currentDateTime();
-    oldestDate = oldestDate.addDays(_maxActivitiesDays * -1);
+    oldestDate = oldestDate.addDays(static_cast<qint64>(_maxActivitiesDays) * -1);
 
     for (const auto &activ : activities) {
         const auto json = activ.toObject();
@@ -423,6 +428,86 @@ void ActivityListModel::ingestActivities(const QJsonArray &activities)
     }
 
     _activityLists.append(list);
+
+    if (list.size() > 0) {
+        std::sort(list.begin(), list.end());
+        beginInsertRows({}, _finalList.size(), _finalList.size() + list.size() - 1);
+        _finalList.append(list);
+        endInsertRows();
+
+        appendMoreActivitiesAvailableEntry();
+    }
+}
+
+void ActivityListModel::appendMoreActivitiesAvailableEntry()
+{
+    const QString moreActivitiesEntryObjectType = QLatin1String("activity_fetch_more_activities");
+    if (_showMoreActivitiesAvailableEntry && !_finalList.isEmpty()
+        && _finalList.last()._objectType != moreActivitiesEntryObjectType) {
+        Activity a;
+        a._type = Activity::ActivityType;
+        a._accName = _accountState->account()->displayName();
+        a._id = -1;
+        a._objectType = moreActivitiesEntryObjectType;
+        a._subject = tr("For more activities please open the Activity app.");
+        a._dateTime = QDateTime::currentDateTime();
+
+        if (const auto *app = _accountState->findApp(QLatin1String("activity"))) {
+            a._link = app->url();
+        }
+
+        beginInsertRows({}, _finalList.size(), _finalList.size());
+        _finalList.append(a);
+        endInsertRows();
+    }
+}
+
+void ActivityListModel::insertOrRemoveDummyFetchingActivity()
+{
+    const QString dummyFetchingActivityObjectType = QLatin1String("dummy_fetching_activity");
+    if (_currentlyFetching && _finalList.isEmpty()) {
+        Activity a;
+        a._type = Activity::ActivityType;
+        a._accName = _accountState->account()->displayName();
+        a._id = -2;
+        a._objectType = dummyFetchingActivityObjectType;
+        a._subject = tr("Fetching activities...");
+        a._dateTime = QDateTime::currentDateTime();
+        a._darkIcon = QLatin1String("qrc:///client/theme/colored/change-bordered.svg");
+        a._lightIcon = QLatin1String("qrc:///client/theme/colored/change-bordered.svg");
+
+        beginInsertRows({}, 0, 0);
+        _finalList.prepend(a);
+        endInsertRows();
+    } else if (!_finalList.isEmpty() && _finalList.first()._objectType == dummyFetchingActivityObjectType) {
+        beginRemoveRows({}, 0, 0);
+        _finalList.removeAt(0);
+        endRemoveRows();
+    }
+}
+
+void ActivityListModel::clearActivities()
+{
+    _activityLists.clear();
+    if (!_finalList.isEmpty()) {
+        const auto firstActivityIt = std::find_if(std::begin(_finalList), std::end(_finalList),
+            [&](const Activity &activity) { return activity._type == Activity::ActivityType; });
+
+        if (firstActivityIt != std::end(_finalList)) {
+            const auto lastActivityItReverse = std::find_if(std::rbegin(_finalList), std::rend(_finalList),
+                    [&](const Activity &activity) { return activity._type == Activity::ActivityType; });
+
+            const auto lastActivityIt = (lastActivityItReverse + 1).base();
+
+            if (lastActivityIt != std::end(_finalList)) {
+                const int beginRemoveIndex = std::distance(std::begin(_finalList), firstActivityIt);
+                const int endRemoveIndex = std::distance(std::begin(_finalList), lastActivityIt);
+                beginRemoveRows({}, beginRemoveIndex, endRemoveIndex);
+                _finalList.erase(firstActivityIt, std::end(_finalList));
+                endRemoveRows();
+            }
+        }
+    }
 }
 
 void ActivityListModel::activitiesReceived(const QJsonDocument &json, int statusCode)
@@ -437,12 +522,10 @@ void ActivityListModel::activitiesReceived(const QJsonDocument &json, int status
         _doneFetching = true;
     }
 
-    _currentlyFetching = false;
+    setAndRefreshCurrentlyFetching(false);
 
     ingestActivities(activities);
 
-    combineActivityLists();
-
     emit activityJobStatusCode(statusCode);
 }
 
@@ -513,8 +596,15 @@ void ActivityListModel::removeActivityFromActivityList(Activity activity)
     int index = -1;
     if (activity._type == Activity::ActivityType) {
         index = _activityLists.indexOf(activity);
-        if (index != -1)
+        if (index != -1) {
             _activityLists.removeAt(index);
+            const auto indexInFinalList = _finalList.indexOf(activity);
+            if (indexInFinalList != -1) {
+                beginRemoveRows({}, indexInFinalList, indexInFinalList);
+                _finalList.removeAt(indexInFinalList);
+                endRemoveRows();
+            }
+        }
     } else if (activity._type == Activity::NotificationType) {
         index = _notificationLists.indexOf(activity);
         if (index != -1)
@@ -744,27 +834,21 @@ void ActivityListModel::combineActivityLists()
     if (_activityLists.count() > 0) {
         std::sort(_activityLists.begin(), _activityLists.end());
         resultList.append(_activityLists);
+    }
 
-        if(_showMoreActivitiesAvailableEntry) {
-            Activity a;
-            a._type = Activity::ActivityType;
-            a._accName = _accountState->account()->displayName();
-            a._id = -1;
-            a._subject = tr("For more activities please open the Activity app.");
-            a._dateTime = QDateTime::currentDateTime();
-
-            AccountApp *app = _accountState->findApp(QLatin1String("activity"));
-            if(app) {
-                a._link = app->url();
-            }
-
-            resultList.append(a);
-        }
+    if (_finalList.isEmpty() && !resultList.isEmpty()) {
+        beginInsertRows({}, 0, resultList.size() - 1);
+        _finalList = resultList;
+        endInsertRows();
+    } else if (!_finalList.isEmpty()) {
+        beginResetModel();
+        _finalList = resultList;
+        endResetModel();
     }
 
-    beginResetModel();
-    _finalList = resultList;
-    endResetModel();
+    if (_activityLists.size() > 0) {
+        appendMoreActivitiesAvailableEntry();
+    }
 }
 
 bool ActivityListModel::canFetchActivities() const
@@ -774,14 +858,14 @@ bool ActivityListModel::canFetchActivities() const
 
 void ActivityListModel::fetchMore(const QModelIndex &)
 {
-    if (canFetchActivities() && !_currentlyFetching) {
+    if (canFetchActivities()) {
         startFetchJob();
     }
 }
 
 void ActivityListModel::slotRefreshActivity()
 {
-    _activityLists.clear();
+    clearActivities();
     _doneFetching = false;
     _currentItem = 0;
     _totalActivitiesFetched = 0;
@@ -795,11 +879,18 @@ void ActivityListModel::slotRefreshActivity()
     }
 }
 
+void ActivityListModel::slotRefreshActivityInitial()
+{
+    if (_activityLists.isEmpty() && !currentlyFetching()) {
+        slotRefreshActivity();
+    }
+}
+
 void ActivityListModel::slotRemoveAccount()
 {
     _finalList.clear();
     _activityLists.clear();
-    _currentlyFetching = false;
+    setAndRefreshCurrentlyFetching(false);
     _doneFetching = false;
     _currentItem = 0;
     _totalActivitiesFetched = 0;
index 43cc211b53ea9723a7b301c1402019a7d308ffde..8ea3a49a17e4ae9411c77b287a46ef17e2839838 100644 (file)
@@ -111,6 +111,7 @@ public:
 
 public slots:
     void slotRefreshActivity();
+    void slotRefreshActivityInitial();
     void slotRemoveAccount();
     void slotTriggerDefaultAction(const int activityIndex);
     void slotTriggerAction(const int activityIndex, const int actionIndex);
@@ -125,7 +126,7 @@ protected:
     void activitiesReceived(const QJsonDocument &json, int statusCode);
     QHash<int, QByteArray> roleNames() const override;
 
-    void setCurrentlyFetching(bool value);
+    void setAndRefreshCurrentlyFetching(bool value);
     bool currentlyFetching() const;
     void setDoneFetching(bool value);
     void setHideOldActivities(bool value);
@@ -147,6 +148,11 @@ private:
     bool canFetchActivities() const;
 
     void ingestActivities(const QJsonArray &activities);
+    void appendMoreActivitiesAvailableEntry();
+
+    void insertOrRemoveDummyFetchingActivity();
+
+    void clearActivities();
 
     ActivityList _activityLists;
     ActivityList _syncFileItemLists;
index f274b80b9bfa2fc0f75e9c79f5bc6d7360936f17..d21f0d7c62a9d6f0c1adb57179597670c46f36f2 100644 (file)
@@ -137,8 +137,6 @@ void ServerNotificationHandler::slotNotificationsReceived(const QJsonDocument &j
                 a._talkNotificationData.userAvatar = ai->account()->url().toString() + QStringLiteral("/index.php/avatar/") + a._subjectRichParameters["user"].id + QStringLiteral("/128");
             }
 
-            list.append(a);
-
             // We want to serve incoming call dialogs to the user for calls that
             if(a._objectType == "call" && a._dateTime.secsTo(QDateTime::currentDateTime()) < 120) {
                 callList.append(a);
index 7bc10a1fb226b88859a6f775cd26b8850ba14108..d7a817748e17a1bf9ca0d222dc166b981e9b4ddd 100644 (file)
@@ -221,7 +221,7 @@ bool User::checkPushNotificationsAreReady() const
 }
 
 void User::slotRefreshImmediately() {
-    if (_account.data() && _account.data()->isConnected()) {
+    if (_account.data() && _account.data()->isConnected() && Systray::instance()->isOpen()) {
         slotRefreshActivities();
     }
     slotRefreshNotifications();
@@ -233,6 +233,7 @@ void User::slotRefresh()
     
     if (checkPushNotificationsAreReady()) {
         // we are relying on WebSocket push notifications - ignore refresh attempts from UI
+        slotRefreshActivitiesInitial();
         _timeSinceLastCheck[_account.data()].invalidate();
         return;
     }
@@ -249,17 +250,24 @@ void User::slotRefresh()
         return;
     }
     if (_account.data() && _account.data()->isConnected()) {
-        if (!timer.isValid()) {
-            slotRefreshActivities();
-        }
+        slotRefreshActivitiesInitial();
         slotRefreshNotifications();
         timer.start();
     }
 }
 
+void User::slotRefreshActivitiesInitial()
+{
+    if (_account.data()->isConnected() && Systray::instance()->isOpen()) {
+        _activityModel->slotRefreshActivityInitial();
+    }
+}
+
 void User::slotRefreshActivities()
 {
-    _activityModel->slotRefreshActivity();
+    if (_account.data()->isConnected() && Systray::instance()->isOpen()) {
+        _activityModel->slotRefreshActivity();
+    }
 }
 
 void User::slotRefreshUserStatus()
index c69e7827b0c69168490a495166bda93bf00410b4..10c9cd1a9b4937b4af7badc1012e4b3ff9fc50d3 100644 (file)
@@ -102,6 +102,7 @@ public slots:
     void slotBuildNotificationDisplay(const ActivityList &list);
     void slotBuildIncomingCallDialogs(const ActivityList &list);
     void slotRefreshNotifications();
+    void slotRefreshActivitiesInitial();
     void slotRefreshActivities();
     void slotRefresh();
     void slotRefreshUserStatus();