diff --git a/include/linphone/api/c-chat-message.h b/include/linphone/api/c-chat-message.h index f028464a2..1cd3dbd21 100644 --- a/include/linphone/api/c-chat-message.h +++ b/include/linphone/api/c-chat-message.h @@ -369,6 +369,8 @@ LINPHONE_PUBLIC const char* linphone_chat_message_get_text_content(const Linphon */ LINPHONE_PUBLIC bool_t linphone_chat_message_is_file_transfer_in_progress(LinphoneChatMessage *msg); +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_message_get_participants_in_state (const LinphoneChatMessage *msg, const LinphoneChatMessageState state); + /** * @} */ diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 902055f9a..a616a9659 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -31,6 +31,7 @@ #include "chat/notification/imdn.h" #include "content/content-type.h" #include "content/content.h" +#include "conference/participant.h" // ============================================================================= @@ -246,6 +247,10 @@ bool_t linphone_chat_message_is_file_transfer_in_progress(LinphoneChatMessage *m return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->isFileTransferInProgress(); } +bctbx_list_t *linphone_chat_message_get_participants_in_state (const LinphoneChatMessage *msg, const LinphoneChatMessageState state) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_PRIVATE_FROM_C_OBJECT(msg)->getParticipantsInState((LinphonePrivate::ChatMessage::State) state)); +} + // ============================================================================= // Old listener // ============================================================================= diff --git a/src/chat/chat-message/chat-message-p.h b/src/chat/chat-message/chat-message-p.h index b665e0d1f..4c957ed71 100644 --- a/src/chat/chat-message/chat-message-p.h +++ b/src/chat/chat-message/chat-message-p.h @@ -59,6 +59,7 @@ public: void setDirection (ChatMessage::Direction dir); void setParticipantState (const IdentityAddress &participantAddress, ChatMessage::State newState); + std::list> getParticipantsInState (const ChatMessage::State state) const; void setState (ChatMessage::State newState, bool force = false); void setTime (time_t time); diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index eb2d1f029..0fcde7521 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -34,6 +34,7 @@ #include "chat/modifier/encryption-chat-message-modifier.h" #include "chat/modifier/file-transfer-chat-message-modifier.h" #include "chat/modifier/multipart-chat-message-modifier.h" +#include "conference/participant.h" #include "content/file-content.h" #include "content/content.h" #include "core/core.h" @@ -122,6 +123,29 @@ void ChatMessagePrivate::setParticipantState (const IdentityAddress &participant setState(ChatMessage::State::DeliveredToUser); } +list> ChatMessagePrivate::getParticipantsInState (const ChatMessage::State state) const { + L_Q(); + + list> participantsInState; + if (!(q->getChatRoom()->getCapabilities() & AbstractChatRoom::Capabilities::Conference) || !dbKey.isValid()) { + return participantsInState; + } + + unique_ptr &mainDb = q->getChatRoom()->getCore()->getPrivate()->mainDb; + shared_ptr eventLog = mainDb->getEventFromKey(dbKey); + list addressesInState = mainDb->getChatMessageParticipantsInState(eventLog, state); + const list> &participants = q->getChatRoom()->getParticipants(); + for (IdentityAddress addr : addressesInState) { + for (const auto &participant : participants) { + if (participant->getAddress() == addr) { + participantsInState.push_back(participant); + } + } + } + + return participantsInState; +} + void ChatMessagePrivate::setState (ChatMessage::State newState, bool force) { L_Q(); diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index 961455882..2b53bda7d 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -39,6 +39,7 @@ class AbstractChatRoom; class Content; class FileTransferContent; class ChatMessagePrivate; +class Participant; class LINPHONE_PUBLIC ChatMessage : public Object, public CoreAccessor { friend class BasicToClientGroupChatRoom; diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index 983630099..e6cfd375d 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -1970,6 +1970,30 @@ list MainDb::getChatMessageParticipantStates (const shared_p }; } +list MainDb::getChatMessageParticipantsInState (const shared_ptr &eventLog, const ChatMessage::State state) const { + return L_DB_TRANSACTION { + L_D(); + + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + MainDbKeyPrivate *dEventKey = static_cast(dEventLog->dbKey).getPrivate(); + const long long &eventId = dEventKey->storageId; + + int stateInt = static_cast(state); + list participantsAddresses; + + static const string query = "SELECT sip_address.value" + " FROM sip_address, chat_message_participant" + " WHERE event_id = :eventId AND state = :state" + " AND sip_address.id = chat_message_participant.participant_sip_address_id"; + soci::rowset rows = (d->dbSession.getBackendSession()->prepare << query, soci::use(eventId), soci::use(stateInt)); + for (const auto &row : rows) { + participantsAddresses.push_back(IdentityAddress(row.get(0))); + } + + return participantsAddresses; + }; +} + ChatMessage::State MainDb::getChatMessageParticipantState ( const shared_ptr &eventLog, const IdentityAddress &participantAddress diff --git a/src/db/main-db.h b/src/db/main-db.h index f0f4b6f06..ae46a5e3e 100644 --- a/src/db/main-db.h +++ b/src/db/main-db.h @@ -91,6 +91,7 @@ public: std::list> getUnreadChatMessages (const ChatRoomId &chatRoomId) const; std::list getChatMessageParticipantStates (const std::shared_ptr &eventLog) const; + std::list getChatMessageParticipantsInState (const std::shared_ptr &eventLog, const ChatMessage::State state) const; ChatMessage::State getChatMessageParticipantState ( const std::shared_ptr &eventLog, const IdentityAddress &participantAddress