diff --git a/src/jamidht/conversation.cpp b/src/jamidht/conversation.cpp index 8111151419481cc466861d8a5d981c0e2bc5fc17..3c4a6711907228a1a864b581382dbde7b1fed284 100644 --- a/src/jamidht/conversation.cpp +++ b/src/jamidht/conversation.cpp @@ -2350,6 +2350,10 @@ void Conversation::onMembersChanged(OnMembersChanged&& cb) { pimpl_->onMembersChanged_ = std::move(cb); + pimpl_->repository_->onMembersChanged([w=weak()] (const std::set<std::string>& memberUris) { + if (auto sthis = w.lock()) + sthis->pimpl_->onMembersChanged_(memberUris); + }); } void diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp index c5c39115d36ac9501bafb60978357eedc3b97177..d5582154ec968be9999072c87deb3863dbfffcf0 100644 --- a/src/jamidht/conversation_module.cpp +++ b/src/jamidht/conversation_module.cpp @@ -770,6 +770,11 @@ ConversationModule::Impl::handlePendingConversation(const std::string& conversat return; } + // Make sure that the list of members stored in convInfos_ matches the + // one from the conversation's repository. + // (https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1026) + setConversationMembers(conversationId, conversation->memberUris("", {})); + lk.lock(); if (conv->pending && conv->pending->socket) @@ -1651,11 +1656,8 @@ ConversationModule::loadConversations() if (convInfo == pimpl_->convInfos_.end()) { JAMI_ERROR("Missing conv info for {}. This is a bug!", repository); sconv->info.created = std::time(nullptr); - sconv->info.members = std::move(members); sconv->info.lastDisplayed = conv->infos()[ConversationMapKeys::LAST_DISPLAYED]; - // convInfosMtx_ is already locked - pimpl_->convInfos_[repository] = sconv->info; } else { sconv->info = convInfo->second; if (convInfo->second.isRemoved()) { @@ -1665,6 +1667,14 @@ ConversationModule::loadConversations() ctx->toRm.insert(repository); } } + // Even if we found the conversation in convInfos_, we cannot assume that the list of members + // stored in `convInfo` is correct (https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1025). + // For this reason, we always use the list we got from the conversation repository to set + // the value of `sconv->info.members`. + members.emplace(acc->getUsername()); + sconv->info.members = std::move(members); + // convInfosMtx_ is already locked + pimpl_->convInfos_[repository] = sconv->info; } auto commits = conv->commitsEndedCalls(); diff --git a/src/jamidht/conversationrepository.cpp b/src/jamidht/conversationrepository.cpp index e8c58c664d15a5f1585a92205c5bdc54394d2818..e6390be8606a1e197848ffca5a9e22c7960a65cd 100644 --- a/src/jamidht/conversationrepository.cpp +++ b/src/jamidht/conversationrepository.cpp @@ -89,12 +89,22 @@ public: } catch (const std::exception& e) { } } + // Note: membersMtx_ needs to be locked when calling saveMembers void saveMembers() { std::ofstream file(membersCache_, std::ios::trunc | std::ios::binary); msgpack::pack(file, members_); + + if (onMembersChanged_) { + std::set<std::string> memberUris; + for (const auto& member : members_) { + memberUris.emplace(member.uri); + } + onMembersChanged_(memberUris); + } } + OnMembersChanged onMembersChanged_ {}; // NOTE! We use temporary GitRepository to avoid to keep file opened (TODO check why // git_remote_fetch() leaves pack-data opened) @@ -2733,7 +2743,7 @@ ConversationRepository::Impl::validCommits( "[conv {}] Malformed joins commit {}. Please check you use the latest version " "of Jami, or that your contact is not doing unwanted stuff.", id_, commit.id); - + emitSignal<libjami::ConversationSignal::OnConversationError>( accountId_, id_, @@ -2750,7 +2760,7 @@ ConversationRepository::Impl::validCommits( "[conv {}] Malformed removes commit {}. Please check you use the latest version " "of Jami, or that your contact is not doing unwanted stuff.", id_, commit.id); - + emitSignal<libjami::ConversationSignal::OnConversationError>( accountId_, id_, @@ -2769,7 +2779,7 @@ ConversationRepository::Impl::validCommits( "[conv {}] Malformed removes commit {}. Please check you use the latest version " "of Jami, or that your contact is not doing unwanted stuff.", id_, commit.id); - + emitSignal<libjami::ConversationSignal::OnConversationError>( accountId_, id_, @@ -2922,6 +2932,12 @@ ConversationRepository::addMember(const std::string& uri) return pimpl_->commit(Json::writeString(wbuilder, json)); } +void +ConversationRepository::onMembersChanged(OnMembersChanged&& cb) +{ + pimpl_->onMembersChanged_ = std::move(cb); +} + std::string ConversationRepository::amend(const std::string& id, const std::string& msg) { diff --git a/src/jamidht/conversationrepository.h b/src/jamidht/conversationrepository.h index c0ffe4dc587cce685810ee7e9e8d621959571a1b..1b7bdc97342ad830c66c6eb6ab4d2cfe7c117fd9 100644 --- a/src/jamidht/conversationrepository.h +++ b/src/jamidht/conversationrepository.h @@ -134,6 +134,7 @@ using PreConditionCb = std::function<CallbackResult(const std::string&, const GitAuthor&, const GitCommit&)>; using PostConditionCb = std::function<bool(const std::string&, const GitAuthor&, ConversationCommit&)>; +using OnMembersChanged = std::function<void(const std::set<std::string>&)>; /** * This class gives access to the git repository that represents the conversation @@ -379,6 +380,8 @@ public: */ void refreshMembers() const; + void onMembersChanged(OnMembersChanged&& cb); + /** * Because conversations can contains non contacts certificates, this methods * loads certificates in conversations into the cert store