diff --git a/core/account.cpp b/core/account.cpp index 094fd3c..21fe9e7 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -434,13 +434,13 @@ void Core::Account::requestArchive(const QString& jid, int count, const QString& if (contact == 0) { qDebug() << "An attempt to request archive for" << jid << "in account" << name << ", but the contact with such id wasn't found, skipping"; - emit responseArchive(jid, std::list()); + emit responseArchive(jid, std::list(), true); return; } if (state != Shared::ConnectionState::connected) { qDebug() << "An attempt to request archive for" << jid << "in account" << name << ", but the account is not online, skipping"; - emit responseArchive(contact->jid, std::list()); + emit responseArchive(contact->jid, std::list(), false); } contact->requestHistory(count, before); @@ -909,3 +909,13 @@ void Core::Account::handleDisconnection() ownVCardRequestInProgress = false; } +void Core::Account::onContactHistoryResponse(const std::list& list, bool last) +{ + RosterItem* contact = static_cast(sender()); + + qDebug() << "Collected history for contact " << contact->jid << list.size() << "elements"; + if (last) { + qDebug() << "The response contains the first accounted message"; + } + emit responseArchive(contact->jid, list, last); +} diff --git a/core/account.h b/core/account.h index 49c7ca9..7b6b50d 100644 --- a/core/account.h +++ b/core/account.h @@ -127,7 +127,7 @@ signals: void removePresence(const QString& jid, const QString& name); void message(const Shared::Message& data); void changeMessage(const QString& jid, const QString& id, const QMap& data); - void responseArchive(const QString& jid, const std::list& list); + void responseArchive(const QString& jid, const std::list& list, bool last); void error(const QString& text); void addRoomParticipant(const QString& jid, const QString& nickName, const QMap& data); void changeRoomParticipant(const QString& jid, const QString& nickName, const QMap& data); @@ -183,6 +183,7 @@ private slots: void onDiscoveryItemsReceived (const QXmppDiscoveryIq& items); void onDiscoveryInfoReceived (const QXmppDiscoveryIq& info); + void onContactHistoryResponse(const std::list& list, bool last); private: void handleDisconnection(); diff --git a/core/archive.cpp b/core/archive.cpp index a1f8b76..f18201b 100644 --- a/core/archive.cpp +++ b/core/archive.cpp @@ -502,8 +502,9 @@ long unsigned int Core::Archive::size() const mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn); MDB_stat stat; mdb_stat(txn, order, &stat); + size_t amount = stat.ms_entries; mdb_txn_abort(txn); - return stat.ms_entries; + return amount; } std::list Core::Archive::getBefore(int count, const QString& id) @@ -603,10 +604,10 @@ void Core::Archive::setFromTheBeginning(bool is) MDB_txn *txn; mdb_txn_begin(environment, NULL, 0, &txn); bool success = setStatValue("beginning", is, txn); - if (success != 0) { - mdb_txn_abort(txn); - } else { + if (success) { mdb_txn_commit(txn); + } else { + mdb_txn_abort(txn); } } } diff --git a/core/handlers/rosterhandler.cpp b/core/handlers/rosterhandler.cpp index 82ca8c3..ce5f1b7 100644 --- a/core/handlers/rosterhandler.cpp +++ b/core/handlers/rosterhandler.cpp @@ -190,7 +190,7 @@ void Core::RosterHandler::removeContactRequest(const QString& jid) void Core::RosterHandler::handleNewRosterItem(Core::RosterItem* contact) { connect(contact, &RosterItem::needHistory, this->acc, &Account::onContactNeedHistory); - connect(contact, &RosterItem::historyResponse, this, &RosterHandler::onContactHistoryResponse); + connect(contact, &RosterItem::historyResponse, this->acc, &Account::onContactHistoryResponse); connect(contact, &RosterItem::nameChanged, this, &RosterHandler::onContactNameChanged); connect(contact, &RosterItem::avatarChanged, this, &RosterHandler::onContactAvatarChanged); connect(contact, &RosterItem::requestVCard, this->acc, &Account::requestVCard); @@ -315,14 +315,6 @@ void Core::RosterHandler::removeFromGroup(const QString& jid, const QString& gro } } -void Core::RosterHandler::onContactHistoryResponse(const std::list& list) -{ - RosterItem* contact = static_cast(sender()); - - qDebug() << "Collected history for contact " << contact->jid << list.size() << "elements"; - emit acc->responseArchive(contact->jid, list); -} - Core::RosterItem * Core::RosterHandler::getRosterItem(const QString& jid) { RosterItem* item = 0; diff --git a/core/handlers/rosterhandler.h b/core/handlers/rosterhandler.h index c01f396..b1dfc45 100644 --- a/core/handlers/rosterhandler.h +++ b/core/handlers/rosterhandler.h @@ -86,7 +86,6 @@ private slots: void onContactGroupRemoved(const QString& group); void onContactNameChanged(const QString& name); void onContactSubscriptionStateChanged(Shared::SubscriptionState state); - void onContactHistoryResponse(const std::list& list); void onContactAvatarChanged(Shared::Avatar, const QString& path); private: diff --git a/core/rosteritem.cpp b/core/rosteritem.cpp index 32b70f4..1baa61f 100644 --- a/core/rosteritem.cpp +++ b/core/rosteritem.cpp @@ -122,7 +122,20 @@ void Core::RosterItem::nextRequest() { if (syncronizing) { if (requestedCount != -1) { - emit historyResponse(responseCache); + bool last = false; + if (archiveState == beginning || archiveState == complete) { + QString firstId = archive->oldestId(); + if (responseCache.size() == 0) { + if (requestedBefore == firstId) { + last = true; + } + } else { + if (responseCache.front().getId() == firstId) { + last = true; + } + } + } + emit historyResponse(responseCache, last); } } if (requestCache.size() > 0) { @@ -529,7 +542,7 @@ void Core::RosterItem::clearArchiveRequests() requestedBefore = ""; for (const std::pair& pair : requestCache) { if (pair.first != -1) { - emit historyResponse(responseCache); //just to notify those who still waits with whatever happened to be left in caches yet + emit historyResponse(responseCache, false); //just to notify those who still waits with whatever happened to be left in caches yet } responseCache.clear(); } diff --git a/core/rosteritem.h b/core/rosteritem.h index 4113b37..e744cac 100644 --- a/core/rosteritem.h +++ b/core/rosteritem.h @@ -81,7 +81,7 @@ public: signals: void nameChanged(const QString& name); void subscriptionStateChanged(Shared::SubscriptionState state); - void historyResponse(const std::list& messages); + void historyResponse(const std::list& messages, bool last); void needHistory(const QString& before, const QString& after, const QDateTime& afterTime = QDateTime()); void avatarChanged(Shared::Avatar, const QString& path); void requestVCard(const QString& jid); diff --git a/core/squawk.cpp b/core/squawk.cpp index 1689d71..9116e47 100644 --- a/core/squawk.cpp +++ b/core/squawk.cpp @@ -357,10 +357,10 @@ void Core::Squawk::requestArchive(const QString& account, const QString& jid, in itr->second->requestArchive(jid, count, before); } -void Core::Squawk::onAccountResponseArchive(const QString& jid, const std::list& list) +void Core::Squawk::onAccountResponseArchive(const QString& jid, const std::list& list, bool last) { Account* acc = static_cast(sender()); - emit responseArchive(acc->getName(), jid, list); + emit responseArchive(acc->getName(), jid, list, last); } void Core::Squawk::modifyAccountRequest(const QString& name, const QMap& map) diff --git a/core/squawk.h b/core/squawk.h index 31812d2..aa84f59 100644 --- a/core/squawk.h +++ b/core/squawk.h @@ -64,7 +64,7 @@ signals: void removePresence(const QString& account, const QString& jid, const QString& name); void stateChanged(Shared::Availability state); void accountMessage(const QString& account, const Shared::Message& data); - void responseArchive(const QString& account, const QString& jid, const std::list& list); + void responseArchive(const QString& account, const QString& jid, const std::list& list, bool last); void addRoom(const QString& account, const QString jid, const QMap& data); void changeRoom(const QString& account, const QString jid, const QMap& data); void removeRoom(const QString& account, const QString jid); @@ -146,7 +146,7 @@ private slots: void onAccountAddPresence(const QString& jid, const QString& name, const QMap& data); void onAccountRemovePresence(const QString& jid, const QString& name); void onAccountMessage(const Shared::Message& data); - void onAccountResponseArchive(const QString& jid, const std::list& list); + void onAccountResponseArchive(const QString& jid, const std::list& list, bool last); void onAccountAddRoom(const QString jid, const QMap& data); void onAccountChangeRoom(const QString jid, const QMap& data); void onAccountRemoveRoom(const QString jid); diff --git a/ui/models/element.cpp b/ui/models/element.cpp index 88d990c..20df389 100644 --- a/ui/models/element.cpp +++ b/ui/models/element.cpp @@ -145,9 +145,9 @@ void Models::Element::changeMessage(const QString& id, const QMap list) +void Models::Element::responseArchive(const std::list list, bool last) { - feed->responseArchive(list); + feed->responseArchive(list, last); } bool Models::Element::isRoom() const diff --git a/ui/models/element.h b/ui/models/element.h index 41cb642..047a645 100644 --- a/ui/models/element.h +++ b/ui/models/element.h @@ -41,7 +41,7 @@ public: void addMessage(const Shared::Message& data); void changeMessage(const QString& id, const QMap& data); unsigned int getMessagesCount() const; - void responseArchive(const std::list list); + void responseArchive(const std::list list, bool last); bool isRoom() const; signals: diff --git a/ui/models/messagefeed.cpp b/ui/models/messagefeed.cpp index 5226ed3..689d0d6 100644 --- a/ui/models/messagefeed.cpp +++ b/ui/models/messagefeed.cpp @@ -166,6 +166,7 @@ bool Models::MessageFeed::canFetchMore(const QModelIndex& parent) const void Models::MessageFeed::fetchMore(const QModelIndex& parent) { if (syncState == incomplete) { + syncState = syncing; emit requestStateChange(true); if (storage.size() == 0) { @@ -176,12 +177,9 @@ void Models::MessageFeed::fetchMore(const QModelIndex& parent) } } -void Models::MessageFeed::responseArchive(const std::list list) +void Models::MessageFeed::responseArchive(const std::list list, bool last) { Storage::size_type size = storage.size(); - if (syncState == syncing) { - emit requestStateChange(false); - } beginInsertRows(QModelIndex(), size, size + list.size() - 1); for (const Shared::Message& msg : list) { @@ -189,6 +187,15 @@ void Models::MessageFeed::responseArchive(const std::list list) storage.insert(copy); } endInsertRows(); + + if (syncState == syncing) { + if (last) { + syncState = complete; + } else { + syncState = incomplete; + } + emit requestStateChange(false); + } } QHash Models::MessageFeed::roleNames() const diff --git a/ui/models/messagefeed.h b/ui/models/messagefeed.h index 0be29a3..e8031ff 100644 --- a/ui/models/messagefeed.h +++ b/ui/models/messagefeed.h @@ -53,7 +53,7 @@ public: void fetchMore(const QModelIndex & parent) override; QHash roleNames() const override; - void responseArchive(const std::list list); + void responseArchive(const std::list list, bool last); unsigned int unreadMessagesCount() const; diff --git a/ui/models/roster.cpp b/ui/models/roster.cpp index 461fbaa..95515b3 100644 --- a/ui/models/roster.cpp +++ b/ui/models/roster.cpp @@ -965,16 +965,16 @@ void Models::Roster::onElementRequestArchive(const QString& before) emit requestArchive(el->getAccountName(), el->getJid(), before); } -void Models::Roster::responseArchive(const QString& account, const QString& jid, const std::list& list) +void Models::Roster::responseArchive(const QString& account, const QString& jid, const std::list& list, bool last) { ElId id(account, jid); std::map::iterator itr = contacts.find(id); if (itr != contacts.end()) { - itr->second->responseArchive(list); + itr->second->responseArchive(list, last); } else { std::map::const_iterator rItr = rooms.find(id); if (rItr != rooms.end()) { - rItr->second->responseArchive(list); + rItr->second->responseArchive(list, last); } } } diff --git a/ui/models/roster.h b/ui/models/roster.h index ac72617..f43d9a9 100644 --- a/ui/models/roster.h +++ b/ui/models/roster.h @@ -80,7 +80,7 @@ public: Account* getAccount(const QString& name); QModelIndex getAccountIndex(const QString& name); QModelIndex getGroupIndex(const QString& account, const QString& name); - void responseArchive(const QString& account, const QString& jid, const std::list& list); + void responseArchive(const QString& account, const QString& jid, const std::list& list, bool last); Accounts* accountsModel; diff --git a/ui/squawk.cpp b/ui/squawk.cpp index 37150d2..1709dd6 100644 --- a/ui/squawk.cpp +++ b/ui/squawk.cpp @@ -610,9 +610,9 @@ void Squawk::onConversationRequestArchive(const QString& account, const QString& emit requestArchive(account, jid, 20, before); //TODO amount as a settings value } -void Squawk::responseArchive(const QString& account, const QString& jid, const std::list& list) +void Squawk::responseArchive(const QString& account, const QString& jid, const std::list& list, bool last) { - rosterModel.responseArchive(account, jid, list); + rosterModel.responseArchive(account, jid, list, last); } void Squawk::removeAccount(const QString& account) diff --git a/ui/squawk.h b/ui/squawk.h index 67013cc..a0d776d 100644 --- a/ui/squawk.h +++ b/ui/squawk.h @@ -97,7 +97,7 @@ public slots: void removePresence(const QString& account, const QString& jid, const QString& name); void stateChanged(Shared::Availability state); void accountMessage(const QString& account, const Shared::Message& data); - void responseArchive(const QString& account, const QString& jid, const std::list& list); + void responseArchive(const QString& account, const QString& jid, const std::list& list, bool last); void addRoom(const QString& account, const QString jid, const QMap& data); void changeRoom(const QString& account, const QString jid, const QMap& data); void removeRoom(const QString& account, const QString jid);