mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-26 23:58:17 +00:00
Add API to get the imdn state of a chat message for each participant.
This commit is contained in:
parent
291bf82bed
commit
532c64bfc4
19 changed files with 530 additions and 53 deletions
|
|
@ -89,6 +89,7 @@ set(C_API_HEADER_FILES
|
|||
c-event-log.h
|
||||
c-magic-search.h
|
||||
c-participant.h
|
||||
c-participant-imdn-state.h
|
||||
c-search-result.h
|
||||
c-types.h
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "linphone/api/c-dial-plan.h"
|
||||
#include "linphone/api/c-event-log.h"
|
||||
#include "linphone/api/c-participant.h"
|
||||
#include "linphone/api/c-participant-imdn-state.h"
|
||||
#include "linphone/api/c-magic-search.h"
|
||||
#include "linphone/api/c-search-result.h"
|
||||
#include "linphone/api/c-types.h"
|
||||
|
|
|
|||
|
|
@ -369,7 +369,26 @@ 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);
|
||||
/**
|
||||
* Gets the list of participants that displayed this message and the time at which they did.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @return \bctbx_list{LinphoneParticipantImdnState}
|
||||
*/
|
||||
LINPHONE_PUBLIC bctbx_list_t *linphone_chat_message_get_participants_that_have_displayed (const LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Gets the list of participants that did not receive this message.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @return \bctbx_list{LinphoneParticipantImdnState}
|
||||
*/
|
||||
LINPHONE_PUBLIC bctbx_list_t *linphone_chat_message_get_participants_that_have_not_received (const LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* Gets the list of participants that received this message and the time at which they did.
|
||||
* @param[in] msg LinphoneChatMessage object
|
||||
* @return \bctbx_list{LinphoneParticipantImdnState}
|
||||
*/
|
||||
LINPHONE_PUBLIC bctbx_list_t *linphone_chat_message_get_participants_that_have_received (const LinphoneChatMessage *msg);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
|
|
|||
91
include/linphone/api/c-participant-imdn-state.h
Normal file
91
include/linphone/api/c-participant-imdn-state.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* c-participant-imdn-state.h
|
||||
* Copyright (C) 2010-2018 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _L_C_PARTICIPANT_IMDN_STATE_H_
|
||||
#define _L_C_PARTICIPANT_IMDN_STATE_H_
|
||||
|
||||
#include "linphone/api/c-types.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // ifdef __cplusplus
|
||||
|
||||
/**
|
||||
* @addtogroup misc
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Increment reference count of LinphoneParticipantImdnState object.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneParticipantImdnState *linphone_participant_imdn_state_ref (LinphoneParticipantImdnState *state);
|
||||
|
||||
/**
|
||||
* Decrement reference count of LinphoneParticipantImdnState object.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_participant_imdn_state_unref (LinphoneParticipantImdnState *state);
|
||||
|
||||
/**
|
||||
* Retrieve the user pointer associated with a LinphoneParticipantImdnState.
|
||||
* @param[in] state A LinphoneParticipantImdnState object
|
||||
* @return The user pointer associated with the LinphoneParticipantImdnState.
|
||||
**/
|
||||
LINPHONE_PUBLIC void *linphone_participant_imdn_state_get_user_data(const LinphoneParticipantImdnState *state);
|
||||
|
||||
/**
|
||||
* Assign a user pointer to a LinphoneParticipantImdnState.
|
||||
* @param[in] state A LinphoneParticipantImdnState object
|
||||
* @param[in] ud The user pointer to associate with the LinphoneParticipantImdnState
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_participant_imdn_state_set_user_data(LinphoneParticipantImdnState *state, void *ud);
|
||||
|
||||
/**
|
||||
* Get the participant concerned by a LinphoneParticipantImdnState.
|
||||
* @param[in] state A LinphoneParticipantImdnState object
|
||||
* @return The participant concerned by the LinphoneParticipantImdnState
|
||||
*/
|
||||
LINPHONE_PUBLIC const LinphoneParticipant *linphone_participant_imdn_state_get_participant (
|
||||
const LinphoneParticipantImdnState *state
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the chat message state the participant is in.
|
||||
* @param state A LinphoneParticipantImdnState object
|
||||
* @return The chat message state the participant is in
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneChatMessageState linphone_participant_imdn_state_get_state (const LinphoneParticipantImdnState *state);
|
||||
|
||||
/**
|
||||
* Get the timestamp at which a participant has reached the state described by a LinphoneParticipantImdnState.
|
||||
* @param[in] state A LinphoneParticipantImdnState object
|
||||
* @return The timestamp at which the participant has reached the state described in the LinphoneParticipantImdnState
|
||||
*/
|
||||
LINPHONE_PUBLIC time_t linphone_participant_imdn_state_get_state_change_time (const LinphoneParticipantImdnState *state);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // ifdef __cplusplus
|
||||
|
||||
#endif // ifndef _L_C_PARTICIPANT_IMDN_STATE_H_
|
||||
|
|
@ -162,6 +162,12 @@ typedef struct _LinphoneMagicSearch LinphoneMagicSearch;
|
|||
**/
|
||||
typedef struct _LinphoneParticipant LinphoneParticipant;
|
||||
|
||||
/**
|
||||
* The LinphoneParticipantImdnState object represents the state of chat message for a participant of a conference chat room.
|
||||
* @ingroup misc
|
||||
**/
|
||||
typedef struct _LinphoneParticipantImdnState LinphoneParticipantImdnState;
|
||||
|
||||
/**
|
||||
* The LinphoneSearchResult object represents a result of a search
|
||||
* @ingroup misc
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
|
|||
conference/params/media-session-params-p.h
|
||||
conference/params/media-session-params.h
|
||||
conference/participant-device.h
|
||||
conference/participant-imdn-state.h
|
||||
conference/participant-imdn-state-p.h
|
||||
conference/participant-p.h
|
||||
conference/participant.h
|
||||
conference/remote-conference-p.h
|
||||
|
|
@ -177,6 +179,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES
|
|||
c-wrapper/api/c-event-log.cpp
|
||||
c-wrapper/api/c-magic-search.cpp
|
||||
c-wrapper/api/c-participant.cpp
|
||||
c-wrapper/api/c-participant-imdn-state.cpp
|
||||
c-wrapper/api/c-search-result.cpp
|
||||
c-wrapper/internal/c-sal.cpp
|
||||
c-wrapper/internal/c-tools.cpp
|
||||
|
|
@ -212,6 +215,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES
|
|||
conference/params/call-session-params.cpp
|
||||
conference/params/media-session-params.cpp
|
||||
conference/participant-device.cpp
|
||||
conference/participant-imdn-state.cpp
|
||||
conference/participant.cpp
|
||||
conference/remote-conference.cpp
|
||||
conference/session/call-session.cpp
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "content/content-type.h"
|
||||
#include "content/content.h"
|
||||
#include "conference/participant.h"
|
||||
#include "conference/participant-imdn-state.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -247,10 +248,19 @@ 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));
|
||||
bctbx_list_t *linphone_chat_message_get_participants_that_have_displayed (const LinphoneChatMessage *msg) {
|
||||
return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getParticipantsThatHaveDisplayed());
|
||||
}
|
||||
|
||||
bctbx_list_t *linphone_chat_message_get_participants_that_have_not_received (const LinphoneChatMessage *msg) {
|
||||
return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getParticipantsThatHaveNotReceived());
|
||||
}
|
||||
|
||||
bctbx_list_t *linphone_chat_message_get_participants_that_have_received (const LinphoneChatMessage *msg) {
|
||||
return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getParticipantsThatHaveReceived());
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Old listener
|
||||
// =============================================================================
|
||||
|
|
|
|||
59
src/c-wrapper/api/c-participant-imdn-state.cpp
Normal file
59
src/c-wrapper/api/c-participant-imdn-state.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* c-participant-imdn-state.cpp
|
||||
* Copyright (C) 2010-2018 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "linphone/api/c-participant-imdn-state.h"
|
||||
|
||||
#include "c-wrapper/c-wrapper.h"
|
||||
#include "conference/participant.h"
|
||||
#include "conference/participant-imdn-state.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
L_DECLARE_C_CLONABLE_OBJECT_IMPL(ParticipantImdnState);
|
||||
|
||||
LinphoneParticipantImdnState *linphone_participant_imdn_state_ref (LinphoneParticipantImdnState *state) {
|
||||
belle_sip_object_ref(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
void linphone_participant_imdn_state_unref (LinphoneParticipantImdnState *state) {
|
||||
belle_sip_object_unref(state);
|
||||
}
|
||||
|
||||
void *linphone_participant_imdn_state_get_user_data(const LinphoneParticipantImdnState *state) {
|
||||
return L_GET_USER_DATA_FROM_C_OBJECT(state);
|
||||
}
|
||||
|
||||
void linphone_participant_imdn_state_set_user_data(LinphoneParticipantImdnState *state, void *ud) {
|
||||
L_SET_USER_DATA_FROM_C_OBJECT(state, ud);
|
||||
}
|
||||
|
||||
const LinphoneParticipant *linphone_participant_imdn_state_get_participant (const LinphoneParticipantImdnState *state) {
|
||||
return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(state)->getParticipant());
|
||||
}
|
||||
|
||||
LinphoneChatMessageState linphone_participant_imdn_state_get_state (const LinphoneParticipantImdnState *state) {
|
||||
return (LinphoneChatMessageState)L_GET_CPP_PTR_FROM_C_OBJECT(state)->getState();
|
||||
}
|
||||
|
||||
time_t linphone_participant_imdn_state_get_state_change_time (const LinphoneParticipantImdnState *state) {
|
||||
return L_GET_CPP_PTR_FROM_C_OBJECT(state)->getStateChangeTime();
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
F(MagicSearch, MagicSearch) \
|
||||
F(MediaSessionParams, CallParams) \
|
||||
F(Participant, Participant) \
|
||||
F(ParticipantImdnState, ParticipantImdnState) \
|
||||
F(SearchResult, SearchResult)
|
||||
|
||||
#define L_REGISTER_SUBTYPES(F) \
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "content/content.h"
|
||||
#include "content/file-content.h"
|
||||
#include "content/file-transfer-content.h"
|
||||
#include "db/main-db.h"
|
||||
#include "db/main-db-chat-message-key.h"
|
||||
#include "event-log/conference/conference-chat-message-event.h"
|
||||
#include "object/object-p.h"
|
||||
|
|
@ -58,8 +59,8 @@ public:
|
|||
|
||||
void setDirection (ChatMessage::Direction dir);
|
||||
|
||||
std::list<ParticipantImdnState> getParticipantsByImdnState (MainDb::ParticipantStateRetrievalFunc func) const;
|
||||
void setParticipantState (const IdentityAddress &participantAddress, ChatMessage::State newState, time_t stateChangeTime);
|
||||
std::list<std::shared_ptr<Participant>> getParticipantsInState (const ChatMessage::State state) const;
|
||||
void setState (ChatMessage::State newState, bool force = false);
|
||||
|
||||
void setTime (time_t time);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "chat/modifier/file-transfer-chat-message-modifier.h"
|
||||
#include "chat/modifier/multipart-chat-message-modifier.h"
|
||||
#include "conference/participant.h"
|
||||
#include "conference/participant-imdn-state.h"
|
||||
#include "content/file-content.h"
|
||||
#include "content/content.h"
|
||||
#include "core/core.h"
|
||||
|
|
@ -70,6 +71,25 @@ void ChatMessagePrivate::setIsReadOnly (bool readOnly) {
|
|||
isReadOnly = readOnly;
|
||||
}
|
||||
|
||||
list<ParticipantImdnState> ChatMessagePrivate::getParticipantsByImdnState (MainDb::ParticipantStateRetrievalFunc func) const {
|
||||
L_Q();
|
||||
|
||||
list<ParticipantImdnState> result;
|
||||
if (!(q->getChatRoom()->getCapabilities() & AbstractChatRoom::Capabilities::Conference) || !dbKey.isValid())
|
||||
return result;
|
||||
|
||||
unique_ptr<MainDb> &mainDb = q->getChatRoom()->getCore()->getPrivate()->mainDb;
|
||||
shared_ptr<EventLog> eventLog = mainDb->getEventFromKey(dbKey);
|
||||
list<MainDb::ParticipantState> dbResults = func(eventLog);
|
||||
for (const auto &dbResult : dbResults) {
|
||||
auto participant = q->getChatRoom()->findParticipant(dbResult.address);
|
||||
if (participant)
|
||||
result.emplace_back(participant, dbResult.state, dbResult.timestamp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ChatMessagePrivate::setParticipantState (const IdentityAddress &participantAddress, ChatMessage::State newState, time_t stateChangeTime) {
|
||||
L_Q();
|
||||
|
||||
|
|
@ -123,29 +143,6 @@ void ChatMessagePrivate::setParticipantState (const IdentityAddress &participant
|
|||
setState(ChatMessage::State::DeliveredToUser);
|
||||
}
|
||||
|
||||
list<shared_ptr<Participant>> ChatMessagePrivate::getParticipantsInState (const ChatMessage::State state) const {
|
||||
L_Q();
|
||||
|
||||
list<shared_ptr<Participant>> participantsInState;
|
||||
if (!(q->getChatRoom()->getCapabilities() & AbstractChatRoom::Capabilities::Conference) || !dbKey.isValid()) {
|
||||
return participantsInState;
|
||||
}
|
||||
|
||||
unique_ptr<MainDb> &mainDb = q->getChatRoom()->getCore()->getPrivate()->mainDb;
|
||||
shared_ptr<EventLog> eventLog = mainDb->getEventFromKey(dbKey);
|
||||
list<IdentityAddress> addressesInState = mainDb->getChatMessageParticipantsInState(eventLog, state);
|
||||
const list<shared_ptr<Participant>> &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();
|
||||
|
||||
|
|
@ -997,6 +994,29 @@ void ChatMessage::setToBeStored (bool value) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
list<ParticipantImdnState> ChatMessage::getParticipantsThatHaveDisplayed () const {
|
||||
L_D();
|
||||
unique_ptr<MainDb> &mainDb = getChatRoom()->getCore()->getPrivate()->mainDb;
|
||||
auto func = bind(&MainDb::getChatMessageParticipantsThatHaveDisplayed, mainDb.get(), std::placeholders::_1);
|
||||
return d->getParticipantsByImdnState(func);
|
||||
}
|
||||
|
||||
list<ParticipantImdnState> ChatMessage::getParticipantsThatHaveNotReceived () const {
|
||||
L_D();
|
||||
unique_ptr<MainDb> &mainDb = getChatRoom()->getCore()->getPrivate()->mainDb;
|
||||
auto func = bind(&MainDb::getChatMessageParticipantsThatHaveNotReceived, mainDb.get(), std::placeholders::_1);
|
||||
return d->getParticipantsByImdnState(func);
|
||||
}
|
||||
|
||||
list<ParticipantImdnState> ChatMessage::getParticipantsThatHaveReceived () const {
|
||||
L_D();
|
||||
unique_ptr<MainDb> &mainDb = getChatRoom()->getCore()->getPrivate()->mainDb;
|
||||
auto func = bind(&MainDb::getChatMessageParticipantsThatHaveReceived, mainDb.get(), std::placeholders::_1);
|
||||
return d->getParticipantsByImdnState(func);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const LinphoneErrorInfo *ChatMessage::getErrorInfo () const {
|
||||
L_D();
|
||||
if (!d->errorInfo) d->errorInfo = linphone_error_info_new(); // let's do it mutable
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class Content;
|
|||
class FileTransferContent;
|
||||
class ChatMessagePrivate;
|
||||
class Participant;
|
||||
class ParticipantImdnState;
|
||||
|
||||
class LINPHONE_PUBLIC ChatMessage : public Object, public CoreAccessor {
|
||||
friend class BasicToClientGroupChatRoom;
|
||||
|
|
@ -94,6 +95,10 @@ public:
|
|||
bool getToBeStored () const;
|
||||
void setToBeStored (bool value);
|
||||
|
||||
std::list<ParticipantImdnState> getParticipantsThatHaveDisplayed () const;
|
||||
std::list<ParticipantImdnState> getParticipantsThatHaveReceived () const;
|
||||
std::list<ParticipantImdnState> getParticipantsThatHaveNotReceived () const;
|
||||
|
||||
const std::list<Content *> &getContents () const;
|
||||
void addContent (Content &content);
|
||||
void removeContent (const Content &content);
|
||||
|
|
|
|||
42
src/conference/participant-imdn-state-p.h
Normal file
42
src/conference/participant-imdn-state-p.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* participant-imdn-state-p.h
|
||||
* Copyright (C) 2010-2018 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _L_PARTICIPANT_IMDN_STATE_P_H_
|
||||
#define _L_PARTICIPANT_IMDN_STATE_P_H_
|
||||
|
||||
#include "object/clonable-object-p.h"
|
||||
|
||||
#include "conference/participant-imdn-state.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class ParticipantImdnStatePrivate : public ClonableObjectPrivate {
|
||||
public:
|
||||
std::shared_ptr<Participant> participant;
|
||||
ChatMessage::State state = ChatMessage::State::Idle;
|
||||
time_t stateChangeTime = 0;
|
||||
|
||||
L_DECLARE_PUBLIC(ParticipantImdnState);
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _L_PARTICIPANT_IMDN_STATE_P_H_
|
||||
61
src/conference/participant-imdn-state.cpp
Normal file
61
src/conference/participant-imdn-state.cpp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* participant-imdn-state.cpp
|
||||
* Copyright (C) 2010-2018 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "participant-imdn-state-p.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
// =============================================================================
|
||||
|
||||
ParticipantImdnState::ParticipantImdnState (const shared_ptr<Participant> &participant, ChatMessage::State state, time_t stateChangeTime)
|
||||
: ClonableObject(*new ParticipantImdnStatePrivate)
|
||||
{
|
||||
L_D();
|
||||
d->participant = participant;
|
||||
d->state = state;
|
||||
d->stateChangeTime = stateChangeTime;
|
||||
}
|
||||
|
||||
ParticipantImdnState::ParticipantImdnState(const ParticipantImdnState &other) : ClonableObject(*new ParticipantImdnStatePrivate) {
|
||||
L_D();
|
||||
d->participant = other.getParticipant();
|
||||
d->state = other.getState();
|
||||
d->stateChangeTime = other.getStateChangeTime();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
shared_ptr<Participant> ParticipantImdnState::getParticipant () const {
|
||||
L_D();
|
||||
return d->participant;
|
||||
}
|
||||
|
||||
ChatMessage::State ParticipantImdnState::getState () const {
|
||||
L_D();
|
||||
return d->state;
|
||||
}
|
||||
|
||||
time_t ParticipantImdnState::getStateChangeTime () const {
|
||||
L_D();
|
||||
return d->stateChangeTime;
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
48
src/conference/participant-imdn-state.h
Normal file
48
src/conference/participant-imdn-state.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* participant-imdn-state.h
|
||||
* Copyright (C) 2010-2018 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _L_PARTICIPANT_IMDN_STATE_H_
|
||||
#define _L_PARTICIPANT_IMDN_STATE_H_
|
||||
|
||||
#include "chat/chat-message/chat-message.h"
|
||||
#include "object/clonable-object.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class Participant;
|
||||
class ParticipantImdnStatePrivate;
|
||||
|
||||
class ParticipantImdnState : public ClonableObject {
|
||||
public:
|
||||
ParticipantImdnState (const std::shared_ptr<Participant> &participant, ChatMessage::State state, time_t stateChangeTime);
|
||||
ParticipantImdnState (const ParticipantImdnState &other);
|
||||
|
||||
std::shared_ptr<Participant> getParticipant () const;
|
||||
ChatMessage::State getState () const;
|
||||
time_t getStateChangeTime () const;
|
||||
|
||||
private:
|
||||
L_DECLARE_PRIVATE(ParticipantImdnState);
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _L_PARTICIPANT_IMDN_STATE_H_
|
||||
|
|
@ -44,6 +44,7 @@ class LINPHONE_PUBLIC Core : public Object {
|
|||
friend class BasicToClientGroupChatRoomPrivate;
|
||||
friend class CallPrivate;
|
||||
friend class CallSession;
|
||||
friend class ChatMessage;
|
||||
friend class ChatMessagePrivate;
|
||||
friend class ChatRoom;
|
||||
friend class ChatRoomPrivate;
|
||||
|
|
|
|||
|
|
@ -1930,6 +1930,85 @@ list<shared_ptr<ChatMessage>> MainDb::getUnreadChatMessages (const ChatRoomId &c
|
|||
};
|
||||
}
|
||||
|
||||
list<MainDb::ParticipantState> MainDb::getChatMessageParticipantsThatHaveDisplayed (
|
||||
const shared_ptr<EventLog> &eventLog
|
||||
) const {
|
||||
return L_DB_TRANSACTION {
|
||||
L_D();
|
||||
|
||||
const EventLogPrivate *dEventLog = eventLog->getPrivate();
|
||||
MainDbKeyPrivate *dEventKey = static_cast<MainDbKey &>(dEventLog->dbKey).getPrivate();
|
||||
const long long &eventId = dEventKey->storageId;
|
||||
int stateInt = static_cast<int>(ChatMessage::State::Displayed);
|
||||
|
||||
static const string query = "SELECT sip_address.value, chat_message_participant.state_change_time"
|
||||
" 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<soci::row> rows = (d->dbSession.getBackendSession()->prepare << query,
|
||||
soci::use(eventId), soci::use(stateInt)
|
||||
);
|
||||
|
||||
list<MainDb::ParticipantState> result;
|
||||
for (const auto &row : rows)
|
||||
result.emplace_back(IdentityAddress(row.get<string>(0)), ChatMessage::State::Displayed, Utils::getTmAsTimeT(row.get<tm>(1)));
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
list<MainDb::ParticipantState> MainDb::getChatMessageParticipantsThatHaveNotReceived (
|
||||
const shared_ptr<EventLog> &eventLog
|
||||
) const {
|
||||
return L_DB_TRANSACTION {
|
||||
L_D();
|
||||
|
||||
const EventLogPrivate *dEventLog = eventLog->getPrivate();
|
||||
MainDbKeyPrivate *dEventKey = static_cast<MainDbKey &>(dEventLog->dbKey).getPrivate();
|
||||
const long long &eventId = dEventKey->storageId;
|
||||
int deliveredStateInt = static_cast<int>(ChatMessage::State::DeliveredToUser);
|
||||
int displayedStateInt = static_cast<int>(ChatMessage::State::Displayed);
|
||||
|
||||
static const string query = "SELECT sip_address.value, chat_message_participant.state_change_time"
|
||||
" FROM sip_address, chat_message_participant"
|
||||
" WHERE event_id = :eventId AND state <> :deliveredState AND state <> :displayedState"
|
||||
" AND sip_address.id = chat_message_participant.participant_sip_address_id";
|
||||
soci::rowset<soci::row> rows = (d->dbSession.getBackendSession()->prepare << query,
|
||||
soci::use(eventId), soci::use(deliveredStateInt), soci::use(displayedStateInt)
|
||||
);
|
||||
|
||||
list<MainDb::ParticipantState> result;
|
||||
for (const auto &row : rows)
|
||||
result.emplace_back(IdentityAddress(row.get<string>(0)), ChatMessage::State::Idle, 0);
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
list<MainDb::ParticipantState> MainDb::getChatMessageParticipantsThatHaveReceived (
|
||||
const shared_ptr<EventLog> &eventLog
|
||||
) const {
|
||||
return L_DB_TRANSACTION {
|
||||
L_D();
|
||||
|
||||
const EventLogPrivate *dEventLog = eventLog->getPrivate();
|
||||
MainDbKeyPrivate *dEventKey = static_cast<MainDbKey &>(dEventLog->dbKey).getPrivate();
|
||||
const long long &eventId = dEventKey->storageId;
|
||||
int stateInt = static_cast<int>(ChatMessage::State::DeliveredToUser);
|
||||
|
||||
static const string query = "SELECT sip_address.value, chat_message_participant.state_change_time"
|
||||
" 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<soci::row> rows = (d->dbSession.getBackendSession()->prepare << query,
|
||||
soci::use(eventId), soci::use(stateInt)
|
||||
);
|
||||
|
||||
list<MainDb::ParticipantState> result;
|
||||
for (const auto &row : rows)
|
||||
result.emplace_back(IdentityAddress(row.get<string>(0)), ChatMessage::State::DeliveredToUser, Utils::getTmAsTimeT(row.get<tm>(1)));
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
list<ChatMessage::State> MainDb::getChatMessageParticipantStates (const shared_ptr<EventLog> &eventLog) const {
|
||||
return L_DB_TRANSACTION {
|
||||
L_D();
|
||||
|
|
@ -1953,30 +2032,6 @@ list<ChatMessage::State> MainDb::getChatMessageParticipantStates (const shared_p
|
|||
};
|
||||
}
|
||||
|
||||
list<IdentityAddress> MainDb::getChatMessageParticipantsInState (const shared_ptr<EventLog> &eventLog, const ChatMessage::State state) const {
|
||||
return L_DB_TRANSACTION {
|
||||
L_D();
|
||||
|
||||
const EventLogPrivate *dEventLog = eventLog->getPrivate();
|
||||
MainDbKeyPrivate *dEventKey = static_cast<MainDbKey &>(dEventLog->dbKey).getPrivate();
|
||||
const long long &eventId = dEventKey->storageId;
|
||||
|
||||
int stateInt = static_cast<int>(state);
|
||||
list<IdentityAddress> 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<soci::row> rows = (d->dbSession.getBackendSession()->prepare << query, soci::use(eventId), soci::use(stateInt));
|
||||
for (const auto &row : rows) {
|
||||
participantsAddresses.push_back(IdentityAddress(row.get<string>(0)));
|
||||
}
|
||||
|
||||
return participantsAddresses;
|
||||
};
|
||||
}
|
||||
|
||||
ChatMessage::State MainDb::getChatMessageParticipantState (
|
||||
const shared_ptr<EventLog> &eventLog,
|
||||
const IdentityAddress &participantAddress
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#ifndef _L_MAIN_DB_H_
|
||||
#define _L_MAIN_DB_H_
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
|
||||
#include "linphone/utils/enum-mask.h"
|
||||
|
|
@ -59,6 +60,15 @@ public:
|
|||
|
||||
typedef EnumMask<Filter> FilterMask;
|
||||
|
||||
struct ParticipantState {
|
||||
ParticipantState (const IdentityAddress &address, ChatMessage::State state, time_t timestamp)
|
||||
: address(address), state(state), timestamp(timestamp) {}
|
||||
|
||||
IdentityAddress address;
|
||||
ChatMessage::State state = ChatMessage::State::Idle;
|
||||
time_t timestamp = 0;
|
||||
};
|
||||
|
||||
MainDb (const std::shared_ptr<Core> &core);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -85,13 +95,23 @@ public:
|
|||
// Conference chat message events.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
using ParticipantStateRetrievalFunc = std::function<std::list<ParticipantState>(const std::shared_ptr<EventLog> &eventLog)>;
|
||||
|
||||
int getChatMessageCount (const ChatRoomId &chatRoomId = ChatRoomId()) const;
|
||||
int getUnreadChatMessageCount (const ChatRoomId &chatRoomId = ChatRoomId()) const;
|
||||
void markChatMessagesAsRead (const ChatRoomId &chatRoomId) const;
|
||||
std::list<std::shared_ptr<ChatMessage>> getUnreadChatMessages (const ChatRoomId &chatRoomId) const;
|
||||
|
||||
std::list<ParticipantState> getChatMessageParticipantsThatHaveDisplayed (
|
||||
const std::shared_ptr<EventLog> &eventLog
|
||||
) const;
|
||||
std::list<ParticipantState> getChatMessageParticipantsThatHaveNotReceived (
|
||||
const std::shared_ptr<EventLog> &eventLog
|
||||
) const;
|
||||
std::list<ParticipantState> getChatMessageParticipantsThatHaveReceived (
|
||||
const std::shared_ptr<EventLog> &eventLog
|
||||
) const;
|
||||
std::list<ChatMessage::State> getChatMessageParticipantStates (const std::shared_ptr<EventLog> &eventLog) const;
|
||||
std::list<IdentityAddress> getChatMessageParticipantsInState (const std::shared_ptr<EventLog> &eventLog, const ChatMessage::State state) const;
|
||||
ChatMessage::State getChatMessageParticipantState (
|
||||
const std::shared_ptr<EventLog> &eventLog,
|
||||
const IdentityAddress &participantAddress
|
||||
|
|
|
|||
|
|
@ -3056,6 +3056,7 @@ static void imdn_for_group_chat_room (void) {
|
|||
stats initialMarieStats = marie->stat;
|
||||
stats initialPaulineStats = pauline->stat;
|
||||
stats initialChloeStats = chloe->stat;
|
||||
time_t initialTime = ms_time(NULL);
|
||||
|
||||
// Enable IMDN
|
||||
linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc));
|
||||
|
|
@ -3090,15 +3091,46 @@ static void imdn_for_group_chat_room (void) {
|
|||
linphone_address_unref(chloeAddr);
|
||||
|
||||
// Check that the message has been delivered to Marie and Pauline
|
||||
BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDeliveredToUser, initialChloeStats.number_of_LinphoneMessageDeliveredToUser + 1, 10000));
|
||||
BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDeliveredToUser, initialChloeStats.number_of_LinphoneMessageDeliveredToUser + 1, 1000));
|
||||
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_that_have_displayed(chloeMessage));
|
||||
bctbx_list_t *participantsThatReceivedChloeMessage = linphone_chat_message_get_participants_that_have_received(chloeMessage);
|
||||
if (BC_ASSERT_PTR_NOT_NULL(participantsThatReceivedChloeMessage)) {
|
||||
BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatReceivedChloeMessage), 2, int, "%d");
|
||||
for (bctbx_list_t *item = participantsThatReceivedChloeMessage; item; item = bctbx_list_next(item)) {
|
||||
LinphoneParticipantImdnState *state = (LinphoneParticipantImdnState *)bctbx_list_get_data(item);
|
||||
BC_ASSERT_GREATER(linphone_participant_imdn_state_get_state_change_time(state), initialTime, int, "%d");
|
||||
BC_ASSERT_EQUAL(linphone_participant_imdn_state_get_state(state), LinphoneChatMessageStateDeliveredToUser, int, "%d");
|
||||
BC_ASSERT_PTR_NOT_NULL(linphone_participant_imdn_state_get_participant(state));
|
||||
}
|
||||
bctbx_list_free_with_data(participantsThatReceivedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref);
|
||||
}
|
||||
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_that_have_not_received(chloeMessage));
|
||||
|
||||
// Marie marks the message as read, check that the state is not yet displayed on Chloe's side
|
||||
linphone_chat_room_mark_as_read(marieCr);
|
||||
BC_ASSERT_FALSE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDisplayed, initialChloeStats.number_of_LinphoneMessageDisplayed + 1, 1000));
|
||||
bctbx_list_t *participantsThatDisplayedChloeMessage = linphone_chat_message_get_participants_that_have_displayed(chloeMessage);
|
||||
if (BC_ASSERT_PTR_NOT_NULL(participantsThatDisplayedChloeMessage)) {
|
||||
BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatDisplayedChloeMessage), 1, int, "%d");
|
||||
bctbx_list_free_with_data(participantsThatDisplayedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref);
|
||||
}
|
||||
participantsThatReceivedChloeMessage = linphone_chat_message_get_participants_that_have_received(chloeMessage);
|
||||
if (BC_ASSERT_PTR_NOT_NULL(participantsThatReceivedChloeMessage)) {
|
||||
BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatReceivedChloeMessage), 1, int, "%d");
|
||||
bctbx_list_free_with_data(participantsThatReceivedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref);
|
||||
}
|
||||
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_that_have_not_received(chloeMessage));
|
||||
|
||||
// Pauline also marks the message as read, check that the state is now displayed on Chloe's side
|
||||
linphone_chat_room_mark_as_read(paulineCr);
|
||||
BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDisplayed, initialChloeStats.number_of_LinphoneMessageDisplayed + 1, 1000));
|
||||
participantsThatDisplayedChloeMessage = linphone_chat_message_get_participants_that_have_displayed(chloeMessage);
|
||||
if (BC_ASSERT_PTR_NOT_NULL(participantsThatDisplayedChloeMessage)) {
|
||||
BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatDisplayedChloeMessage), 2, int, "%d");
|
||||
bctbx_list_free_with_data(participantsThatDisplayedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref);
|
||||
}
|
||||
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_that_have_received(chloeMessage));
|
||||
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_that_have_not_received(chloeMessage));
|
||||
|
||||
linphone_chat_message_unref(chloeMessage);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue