Experimental async starred msg marking. - #71

This commit is contained in:
martinrotter 2017-04-28 08:41:38 +02:00
parent 858184b6ff
commit d0b19b7361
8 changed files with 89 additions and 37 deletions

View File

@ -101,3 +101,12 @@ Message Message::fromSqlRecord(const QSqlRecord &record, bool *result) {
return message; return message;
} }
uint qHash(Message key, uint seed) {
Q_UNUSED(seed)
return (key.m_accountId * 10000) + key.m_id;
}
uint qHash(const Message &key) {
return (key.m_accountId * 10000) + key.m_id;
}

View File

@ -69,6 +69,17 @@ class Message {
// Is true if "created" date was obtained directly // Is true if "created" date was obtained directly
// from the feed, otherwise is false // from the feed, otherwise is false
bool m_createdFromFeed; bool m_createdFromFeed;
friend inline bool operator==(const Message &lhs, const Message &rhs) {
return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id;
}
friend inline bool operator!=(const Message &lhs, const Message &rhs) {
return !(lhs == rhs);
}
}; };
uint qHash(Message key, uint seed);
uint qHash(const Message &key);
#endif // MESSAGE_H #endif // MESSAGE_H

View File

@ -189,7 +189,7 @@ void MessagePreviewer::switchMessageImportance(bool checked) {
DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings),
QStringList() << QString::number(m_message.m_id)); QStringList() << QString::number(m_message.m_id));
m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(),
QList<ImportanceChange>() << ImportanceChange(m_message, QList<ImportanceChange>() << ImportanceChange(m_message,
m_message.m_isImportant ? m_message.m_isImportant ?
RootItem::NotImportant : RootItem::NotImportant :

View File

@ -290,7 +290,7 @@ void WebBrowser::switchMessageImportance(int id, bool checked) {
DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings),
QStringList() << QString::number(msg->m_id)); QStringList() << QString::number(msg->m_id));
m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(),
QList<ImportanceChange>() << ImportanceChange(*msg, QList<ImportanceChange>() << ImportanceChange(*msg,
msg->m_isImportant ? msg->m_isImportant ?
RootItem::NotImportant : RootItem::NotImportant :

View File

@ -24,13 +24,34 @@
CacheForServiceRoot::CacheForServiceRoot() : m_cacheSaveMutex(new Mutex(QMutex::NonRecursive, nullptr)), CacheForServiceRoot::CacheForServiceRoot() : m_cacheSaveMutex(new Mutex(QMutex::NonRecursive, nullptr)),
m_cachedStatesRead(QMap<RootItem::ReadStatus, QStringList>()), m_cachedStatesRead(QMap<RootItem::ReadStatus, QStringList>()),
m_cachedStatesImportant(QMap<RootItem::Importance, QStringList>()) { m_cachedStatesImportant(QMap<RootItem::Importance, QList<Message>>()) {
} }
CacheForServiceRoot::~CacheForServiceRoot() { CacheForServiceRoot::~CacheForServiceRoot() {
m_cacheSaveMutex->deleteLater(); m_cacheSaveMutex->deleteLater();
} }
void CacheForServiceRoot::addMessageStatesToCache(const QList<Message> &ids_of_messages, RootItem::Importance importance) {
m_cacheSaveMutex->lock();
QList<Message> &list_act = m_cachedStatesImportant[importance];
QList<Message> &list_other = m_cachedStatesImportant[importance == RootItem::Important ? RootItem::NotImportant : RootItem::Important];
// Store changes, they will be sent to server later.
list_act.append(ids_of_messages);
QSet<Message> set_act = list_act.toSet();
QSet<Message> set_other = list_other.toSet();
// Now, we want to remove all IDS from list_other, which are contained in list.
set_other -= set_act;
list_act.clear(); list_act.append(set_act.toList());
list_other.clear(); list_other.append(set_other.toList());
m_cacheSaveMutex->unlock();
}
void CacheForServiceRoot::addMessageStatesToCache(const QStringList &ids_of_messages, RootItem::ReadStatus read) { void CacheForServiceRoot::addMessageStatesToCache(const QStringList &ids_of_messages, RootItem::ReadStatus read) {
m_cacheSaveMutex->lock(); m_cacheSaveMutex->lock();
@ -52,20 +73,20 @@ void CacheForServiceRoot::addMessageStatesToCache(const QStringList &ids_of_mess
m_cacheSaveMutex->unlock(); m_cacheSaveMutex->unlock();
} }
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QStringList> > CacheForServiceRoot::takeMessageCache() { QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>> > CacheForServiceRoot::takeMessageCache() {
m_cacheSaveMutex->lock(); m_cacheSaveMutex->lock();
if (m_cachedStatesRead.isEmpty() && m_cachedStatesImportant.isEmpty()) { if (m_cachedStatesRead.isEmpty() && m_cachedStatesImportant.isEmpty()) {
// No cached changes. // No cached changes.
m_cacheSaveMutex->unlock(); m_cacheSaveMutex->unlock();
return QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QStringList> >(); return QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>> >();
} }
// Make copy of changes. // Make copy of changes.
QMap<RootItem::ReadStatus, QStringList> cached_data_read = m_cachedStatesRead; QMap<RootItem::ReadStatus, QStringList> cached_data_read = m_cachedStatesRead;
cached_data_read.detach(); cached_data_read.detach();
QMap<RootItem::Importance, QStringList> cached_data_imp = m_cachedStatesImportant; QMap<RootItem::Importance, QList<Message>> cached_data_imp = m_cachedStatesImportant;
cached_data_imp.detach(); cached_data_imp.detach();
m_cachedStatesRead.clear(); m_cachedStatesRead.clear();
@ -73,5 +94,5 @@ QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QStrin
m_cacheSaveMutex->unlock(); m_cacheSaveMutex->unlock();
return QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QStringList> >(cached_data_read, cached_data_imp); return QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>> >(cached_data_read, cached_data_imp);
} }

View File

@ -32,14 +32,15 @@ class CacheForServiceRoot {
explicit CacheForServiceRoot(); explicit CacheForServiceRoot();
virtual ~CacheForServiceRoot(); virtual ~CacheForServiceRoot();
void addMessageStatesToCache(const QList<Message> &ids_of_messages, RootItem::Importance importance);
void addMessageStatesToCache(const QStringList &ids_of_messages, RootItem::ReadStatus read); void addMessageStatesToCache(const QStringList &ids_of_messages, RootItem::ReadStatus read);
protected: protected:
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QStringList>> takeMessageCache(); QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message> > > takeMessageCache();
Mutex *m_cacheSaveMutex; Mutex *m_cacheSaveMutex;
QMap<RootItem::ReadStatus, QStringList> m_cachedStatesRead; QMap<RootItem::ReadStatus, QStringList> m_cachedStatesRead;
QMap<RootItem::Importance, QStringList> m_cachedStatesImportant; QMap<RootItem::Importance, QList<Message>> m_cachedStatesImportant;
}; };
#endif // CACHEFORSERVICEROOT_H #endif // CACHEFORSERVICEROOT_H

View File

@ -118,7 +118,7 @@ OwnCloudNetworkFactory *OwnCloudServiceRoot::network() const {
} }
void OwnCloudServiceRoot::saveAllCachedData() { void OwnCloudServiceRoot::saveAllCachedData() {
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QStringList>> msgCache = takeMessageCache(); QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> msgCache = takeMessageCache();
QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first); QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first);
// Save the actual data read/unread. // Save the actual data read/unread.
@ -131,6 +131,26 @@ void OwnCloudServiceRoot::saveAllCachedData() {
network()->markMessagesRead(key, ids); network()->markMessagesRead(key, ids);
} }
} }
QMapIterator<RootItem::Importance, QList<Message>> j(msgCache.second);
// Save the actual data important/not important.
while (j.hasNext()) {
j.next();
auto key = j.key();
QList<Message> messages = j.value();
if (!messages.isEmpty()) {
QStringList feed_ids, guid_hashes;
foreach (const Message &msg, messages) {
feed_ids.append(msg.m_feedId);
guid_hashes.append(msg.m_customHash);
}
network()->markMessagesStarred(key, feed_ids, guid_hashes);
}
}
} }
bool OwnCloudServiceRoot::onBeforeSetMessagesRead(RootItem *selected_item, bool OwnCloudServiceRoot::onBeforeSetMessagesRead(RootItem *selected_item,
@ -147,34 +167,24 @@ bool OwnCloudServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_ite
Q_UNUSED(selected_item) Q_UNUSED(selected_item)
// Now, we need to separate the changes because of ownCloud API limitations. // Now, we need to separate the changes because of ownCloud API limitations.
QStringList mark_starred_feed_ids, mark_starred_guid_hashes; QList<Message> mark_starred_msgs;
QStringList mark_unstarred_feed_ids, mark_unstarred_guid_hashes; QList<Message> mark_unstarred_msgs;
foreach (const ImportanceChange &pair, changes) { foreach (const ImportanceChange &pair, changes) {
if (pair.second == RootItem::Important) { if (pair.second == RootItem::Important) {
mark_starred_feed_ids.append(pair.first.m_feedId); mark_starred_msgs.append(pair.first);
mark_starred_guid_hashes.append(pair.first.m_customHash);
} }
else { else {
mark_unstarred_feed_ids.append(pair.first.m_feedId); mark_unstarred_msgs.append(pair.first);
mark_unstarred_guid_hashes.append(pair.first.m_customHash);
} }
} }
// OK, now perform the online update itself. if (!mark_starred_msgs.isEmpty()) {
addMessageStatesToCache(mark_starred_msgs, RootItem::Important);
if (!mark_starred_feed_ids.isEmpty()) {
if (network()->markMessagesStarred(RootItem::Important, mark_starred_feed_ids, mark_starred_guid_hashes) !=
QNetworkReply::NoError) {
return false;
}
} }
if (!mark_unstarred_feed_ids.isEmpty()) { if (!mark_unstarred_msgs.isEmpty()) {
if (network()->markMessagesStarred(RootItem::NotImportant, mark_unstarred_feed_ids, mark_unstarred_guid_hashes) != addMessageStatesToCache(mark_unstarred_msgs, RootItem::NotImportant);
QNetworkReply::NoError) {
return false;
}
} }
return true; return true;

View File

@ -170,7 +170,7 @@ void TtRssServiceRoot::saveAllCachedData() {
return false; return false;
}*/ }*/
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QStringList>> msgCache = takeMessageCache(); QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> msgCache = takeMessageCache();
QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first); QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first);
// Save the actual data read/unread. // Save the actual data read/unread.