From 1b99beebc5c4811d7ca16b53539cfc51f42e05ae Mon Sep 17 00:00:00 2001 From: jolavillette Date: Sat, 1 Aug 2026 23:03:27 +0200 Subject: [PATCH] Address review: pointer hand-off to the workers, event-driven board update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GxsForumModel / PostedPostsModel: hand the id list to the background worker through a pointer deleted after the call, so the lambda capture does not deep copy it. - PostedPostsModel: setAllMsgReadStatus() no longer updates the model directly. The batched READ_STATUS_CHANGED event now carries the affected ids and their new state (libretroshare side), and the event handler applies them locally — so a batch initiated by another frontend (e.g. webUI) updates the board view exactly the same way, and no post is re-read from the database. Co-Authored-By: Claude Fable 5 --- .../src/gui/Posted/PostedPostsModel.cpp | 49 ++++++++++++++----- .../src/gui/gxsforums/GxsForumModel.cpp | 11 ++++- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/retroshare-gui/src/gui/Posted/PostedPostsModel.cpp b/retroshare-gui/src/gui/Posted/PostedPostsModel.cpp index cd014168a..e827a2fbb 100644 --- a/retroshare-gui/src/gui/Posted/PostedPostsModel.cpp +++ b/retroshare-gui/src/gui/Posted/PostedPostsModel.cpp @@ -79,6 +79,31 @@ void RsPostedPostsModel::handleEvent_main_thread(std::shared_ptr case RsPostedEventCode::MESSAGE_VOTES_UPDATED: case RsPostedEventCode::NEW_MESSAGE: { + // Batched read-status change ("mark all as read", possibly issued by + // another frontend such as the webUI): the event carries the affected + // message ids and their new state, so update the flags locally + // instead of re-reading the posts from the database. + if( e->mPostedEventCode == RsPostedEventCode::READ_STATUS_CHANGED + && !e->mPostedMsgIds.empty() ) + { + if(e->mPostedGroupId != mPostedGroup.mMeta.mGroupId) + return; + + const std::set ids(e->mPostedMsgIds.begin(),e->mPostedMsgIds.end()); + + for(uint32_t i=0;imPostedMsgsRead) + mPosts[i].mMeta.mMsgStatus &= ~(GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD | GXS_SERV::GXS_MSG_STATUS_GUI_NEW); + else + mPosts[i].mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + } + + emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mDisplayedNbPosts-1,0,(void*)NULL)); + return; + } + // Normally we should just emit dataChanged() on the index of the data that has changed: // // We need to update the data! @@ -754,21 +779,21 @@ void RsPostedPostsModel::setAllMsgReadStatus(bool read) } if(!msgIds.empty()) - RsThread::async([boardId=mPostedGroup.mMeta.mGroupId, msgIds, read]() + { + // Hand the id list over through a pointer: the lambda capture would + // otherwise deep copy it. + auto* ids = new std::vector(std::move(msgIds)); + + RsThread::async([boardId=mPostedGroup.mMeta.mGroupId, ids, read]() { - rsPosted->setPostReadStatus(boardId, msgIds, read); + rsPosted->setPostReadStatus(boardId, *ids, read); + delete ids; } ); + } - // Update the local model immediately, since we don't catch the resulting - // event later (that would reload the posts). - - for(uint32_t i=0;imarkRead(std::make_pair(grpId, msgId), read_status); }); else if(!changed_msgs.empty()) - RsThread::async( [grpId=mForumGroup.mMeta.mGroupId,changed_msgs,read_status]() + { + // Hand the (possibly long) id list over through a pointer: the lambda + // capture would otherwise deep copy it. + auto* msgs = new std::vector(std::move(changed_msgs)); + + RsThread::async( [grpId=mForumGroup.mMeta.mGroupId,msgs,read_status]() { - rsGxsForums->markRead(grpId, changed_msgs, read_status); + rsGxsForums->markRead(grpId, *msgs, read_status); + delete msgs; }); + } // How the view is refreshed depends on how many *rows* changed, not on how // many messages were written. A post keeps every edited version of itself in