diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index b4f18124d..fdcc6743c 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -533,7 +533,14 @@ void WireDialog::addGroup(const RsWireGroup &group) std::cerr << "WireDialog::addGroup() GroupId : " << group.mMeta.mGroupId; std::cerr << std::endl; - addGroup(new WireGroupItem(this, group)); + WireGroupItem *item = new WireGroupItem(this, group); + + // Apply cached unread count so the badge is correct from the moment the item appears + auto sit = mCachedGroupStats.find(group.mMeta.mGroupId); + if (sit != mCachedGroupStats.end()) + item->setUnreadCount(sit->second.mNumThreadMsgsUnread); + + addGroup(item); } void WireDialog::deleteGroups() @@ -578,6 +585,12 @@ void WireDialog::updateGroups(const std::vector& groups) for(auto &it : groups) { // save list of all groups. mAllGroups[it.mMeta.mGroupId] = it; + + if (it.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) { + mOwnGroups.push_back(it); + } + + addGroup(it); if (it.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { @@ -1382,13 +1395,13 @@ void WireDialog::updateGroupStatisticsReal(const RsGxsGroupId &groupId) * Qt::QueuedConnection is important! */ -// QTreeWidgetItem *item = ui.scrollAreaWidgetContents->getItemFromId(QString::fromStdString(stats.mGrpId.toStdString())); - -// if (item) -// ui.scrollAreaWidgetContents->setUnreadCount(item, mCountChildMsgs ? (stats.mNumThreadMsgsUnread + stats.mNumChildMsgsUnread) : stats.mNumThreadMsgsUnread); - mCachedGroupStats[groupId] = stats; + // Update the unread count badge on the matching WireGroupItem + WireGroupItem *groupItem = findGroupItemWidget(groupId); + if (groupItem) + groupItem->setUnreadCount(stats.mNumThreadMsgsUnread); + getUserNotify()->updateIcon(); }, this ); @@ -1455,6 +1468,20 @@ GxsMessageFrameWidget *WireDialog::messageWidget(const RsGxsGroupId &groupId) return NULL; } +WireGroupItem *WireDialog::findGroupItemWidget(const RsGxsGroupId &groupId) +{ + QLayout *alayout = ui.groupsWidget->layout(); + for (int i = 0; i < alayout->count(); ++i) + { + QLayoutItem *item = alayout->itemAt(i); + if (!item) continue; + WireGroupItem *groupItem = dynamic_cast(item->widget()); + if (groupItem && groupItem->groupId() == groupId) + return groupItem; + } + return nullptr; +} + //void GxsGroupFrameDialog::changedCurrentGroup(const QString& groupId) //{ // if (mInFill) { @@ -1494,3 +1521,31 @@ GxsMessageFrameWidget *WireDialog::messageWidget(const RsGxsGroupId &groupId) // currentWidget()->setGroupId(mGroupId); // } //} + +void WireDialog::markGroupAsRead(const RsGxsGroupId &groupId) +{ + // Fetch all message summaries in the background and mark each as read. + RsThread::async([this, groupId]() + { + std::vector summaries; + if (!rsWire->getContentSummaries(groupId, summaries)) + { + std::cerr << "WireDialog::markGroupAsRead() failed to get summaries for group " + << groupId << std::endl; + return; + } + + for (auto &meta : summaries) + { + uint32_t token; + RsGxsGrpMsgIdPair msgIdPair(groupId, meta.mMsgId); + rsWire->setMessageReadStatus(token, msgIdPair, true); + } + + // Refresh statistics and notify icon from the GUI thread. + RsQThreadUtils::postToObject([this, groupId]() + { + updateGroupStatisticsReal(groupId); + }, this); + }); +} diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index 185b99a7f..51c9c7a52 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -125,6 +125,8 @@ public: void getServiceStatistics(GxsServiceStatistic& stats) const override; virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId); + + virtual void markGroupAsRead(const RsGxsGroupId &groupId) override; protected: @@ -132,6 +134,7 @@ protected: UserNotify *createUserNotify(QObject *parent) override; virtual void updateGroupStatistics(const RsGxsGroupId &groupId); virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId); + std::map mGroupStats; private slots: @@ -178,6 +181,7 @@ private: void requestGroupData(); GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId); + WireGroupItem *findGroupItemWidget(const RsGxsGroupId &groupId); int mGroupSet; diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp index 63d771896..9ab2aba57 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp @@ -77,7 +77,11 @@ RsGxsGroupId &WireGroupItem::groupId() void WireGroupItem::setup() { - label_groupName->setText(QString::fromStdString(mGroup.mMeta.mGroupName)); + // Initialize cached members from group data + mGroupId = mGroup.mMeta.mGroupId; + mGroupName = QString::fromStdString(mGroup.mMeta.mGroupName); + + label_groupName->setText(mGroupName); label_authorId->setId(mGroup.mMeta.mAuthorId); frame_details->setVisible(false); @@ -119,6 +123,7 @@ void WireGroupItem::setup() connect(toolButton_show, SIGNAL(clicked()), this, SLOT(show())); connect(toolButton_subscribe, SIGNAL(clicked()), this, SLOT(subscribe())); connect(editButton, SIGNAL(clicked()), this, SLOT(editGroupDetails())); + toolButton_readAll->hide(); // hidden until we know there are unread messages setGroupSet(); } @@ -234,3 +239,21 @@ void WireGroupItem::editGroupDetails() WireGroupDialog wireEdit(GxsGroupDialog::MODE_EDIT, groupId, this); wireEdit.exec (); } + +void WireGroupItem::setUnreadCount(uint32_t count) +{ + if (count > 0) { + // Make text bold and show count + label_groupName->setText(QString("%1 (%2)").arg(mGroupName).arg(count)); + toolButton_readAll->show(); + } else { + // Regular text + label_groupName->setText(mGroupName); + toolButton_readAll->hide(); + } +} + +void WireGroupItem::on_toolButton_readAll_clicked() +{ + mHolder->markGroupAsRead(mGroup.mMeta.mGroupId); +} diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.h b/retroshare-gui/src/gui/TheWire/WireGroupItem.h index 522a1ccc2..41b893c83 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.h +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.h @@ -35,6 +35,7 @@ public: virtual void unsubscribe(RsGxsGroupId &groupId) = 0; virtual void notifyGroupSelection(WireGroupItem *item) = 0; + virtual void markGroupAsRead(const RsGxsGroupId &groupId) = 0; }; class WireGroupItem : public QWidget, private Ui::WireGroupItem @@ -52,11 +53,13 @@ public: const QPixmap *getPixmap(); RsGxsGroupId &groupId(); bool matchesFilter(const QString &filterText) const; + void setUnreadCount(uint32_t count); private slots: void show(); void subscribe(); void editGroupDetails(); + void on_toolButton_readAll_clicked(); protected: void mousePressEvent(QMouseEvent *event); @@ -66,6 +69,8 @@ private: void setGroupSet(); void setBackground(QColor color); + RsGxsGroupId mGroupId; + QString mGroupName; WireGroupHolder *mHolder; RsWireGroup mGroup; bool mSelected; diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui index a53448157..923481646 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui @@ -6,7 +6,7 @@ 0 0 - 292 + 302 115 @@ -153,6 +153,20 @@ + + + + Mark all as read all + + + ... + + + + :/icons/png/correct.png:/icons/png/correct.png + + +