Commit 55050265 authored by Ghislain MARY's avatar Ghislain MARY

Simplify API to get IMDN message state for each participants.

parent cb8928e6
......@@ -381,25 +381,13 @@ LINPHONE_PUBLIC const char *linphone_chat_message_get_text_content (const Linpho
LINPHONE_PUBLIC bool_t linphone_chat_message_is_file_transfer_in_progress (LinphoneChatMessage *msg);
/**
* Gets the list of participants that displayed this message and the time at which they did.
* Gets the list of participants for which the imdn state has reached the specified state and the time at which they did.
* @param[in] msg #LinphoneChatMessage object.
* @param[in] state The LinphoneChatMessageState the imdn have reached (only use LinphoneChatMessageStateDelivered,
* LinphoneChatMessageStateDeliveredToUser, LinphoneChatMessageStateDisplayed and LinphoneChatMessageStateNotDelivered)
* @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);
LINPHONE_PUBLIC bctbx_list_t *linphone_chat_message_get_participants_by_imdn_state (const LinphoneChatMessage *msg, LinphoneChatMessageState state);
/**
* @}
......
......@@ -251,16 +251,8 @@ 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_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());
bctbx_list_t *linphone_chat_message_get_participants_by_imdn_state (const LinphoneChatMessage *msg, LinphoneChatMessageState state) {
return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getParticipantsByImdnState(LinphonePrivate::ChatMessage::State(state)));
}
......
......@@ -60,7 +60,6 @@ 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);
virtual void setState (ChatMessage::State newState, bool force = false);
......
......@@ -71,26 +71,6 @@ 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 sender = q->getChatRoom()->findParticipant(q->getFromAddress());
auto participant = q->getChatRoom()->findParticipant(dbResult.address);
if (participant && (participant != sender))
result.emplace_back(participant, dbResult.state, dbResult.timestamp);
}
return result;
}
void ChatMessagePrivate::setParticipantState (const IdentityAddress &participantAddress, ChatMessage::State newState, time_t stateChangeTime) {
L_Q();
......@@ -1018,25 +998,24 @@ void ChatMessage::setToBeStored (bool value) {
// -----------------------------------------------------------------------------
list<ParticipantImdnState> ChatMessage::getParticipantsThatHaveDisplayed () const {
list<ParticipantImdnState> ChatMessage::getParticipantsByImdnState (ChatMessage::State state) 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> result;
if (!(getChatRoom()->getCapabilities() & AbstractChatRoom::Capabilities::Conference) || !d->dbKey.isValid())
return result;
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);
shared_ptr<EventLog> eventLog = mainDb->getEventFromKey(d->dbKey);
list<MainDb::ParticipantState> dbResults = mainDb->getChatMessageParticipantsByImdnState(eventLog, state);
for (const auto &dbResult : dbResults) {
auto sender = getChatRoom()->findParticipant(getFromAddress());
auto participant = getChatRoom()->findParticipant(dbResult.address);
if (participant && (participant != sender))
result.emplace_back(participant, dbResult.state, dbResult.timestamp);
}
return result;
}
// -----------------------------------------------------------------------------
......
......@@ -94,9 +94,7 @@ public:
bool getToBeStored () const;
virtual void setToBeStored (bool value);
std::list<ParticipantImdnState> getParticipantsThatHaveDisplayed () const;
std::list<ParticipantImdnState> getParticipantsThatHaveReceived () const;
std::list<ParticipantImdnState> getParticipantsThatHaveNotReceived () const;
std::list<ParticipantImdnState> getParticipantsByImdnState (State state) const;
const std::list<Content *> &getContents () const;
void addContent (Content *content);
......
......@@ -150,6 +150,13 @@ private:
long long insertConferenceParticipantDeviceEvent (const std::shared_ptr<EventLog> &eventLog);
long long insertConferenceSubjectEvent (const std::shared_ptr<EventLog> &eventLog);
void setChatMessageParticipantState (
const std::shared_ptr<EventLog> &eventLog,
const IdentityAddress &participantAddress,
ChatMessage::State state,
time_t stateChangeTime
);
// ---------------------------------------------------------------------------
// Cache API.
// ---------------------------------------------------------------------------
......
......@@ -779,6 +779,13 @@ void MainDbPrivate::updateConferenceChatMessageEvent (const shared_ptr<EventLog>
deleteContents(eventId);
for (const auto &content : chatMessage->getContents())
insertContent(eventId, *content);
if ((chatMessage->getDirection() == ChatMessage::Direction::Outgoing)
&& ((chatMessage->getState() == ChatMessage::State::Delivered) || (chatMessage->getState() == ChatMessage::State::NotDelivered))
) {
for (const auto &participant : chatMessage->getChatRoom()->getParticipants())
setChatMessageParticipantState(eventLog, participant->getAddress(), chatMessage->getState(), std::time(nullptr));
}
}
long long MainDbPrivate::insertConferenceNotifiedEvent (const shared_ptr<EventLog> &eventLog, long long *chatRoomId) {
......@@ -904,6 +911,26 @@ long long MainDbPrivate::insertConferenceSubjectEvent (const shared_ptr<EventLog
return eventId;
}
void MainDbPrivate::setChatMessageParticipantState (
const shared_ptr<EventLog> &eventLog,
const IdentityAddress &participantAddress,
ChatMessage::State state,
time_t stateChangeTime
) {
const EventLogPrivate *dEventLog = eventLog->getPrivate();
MainDbKeyPrivate *dEventKey = static_cast<MainDbKey &>(dEventLog->dbKey).getPrivate();
const long long &eventId = dEventKey->storageId;
const long long &participantSipAddressId = selectSipAddressId(participantAddress.asString());
int stateInt = static_cast<int>(state);
const tm &stateChangeTm = Utils::getTimeTAsTm(stateChangeTime);
*dbSession.getBackendSession() << "UPDATE chat_message_participant SET state = :state,"
" state_change_time = :stateChangeTm"
" WHERE event_id = :eventId AND participant_sip_address_id = :participantSipAddressId",
soci::use(stateInt), soci::use(stateChangeTm), soci::use(eventId), soci::use(participantSipAddressId);
}
// -----------------------------------------------------------------------------
// Cache API.
// -----------------------------------------------------------------------------
......@@ -1961,61 +1988,9 @@ 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, MainDbPrivate::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
list<MainDb::ParticipantState> MainDb::getChatMessageParticipantsByImdnState (
const shared_ptr<EventLog> &eventLog,
ChatMessage::State state
) const {
return L_DB_TRANSACTION {
L_D();
......@@ -2023,7 +1998,7 @@ list<MainDb::ParticipantState> MainDb::getChatMessageParticipantsThatHaveReceive
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);
int stateInt = static_cast<int>(state);
static const string query = "SELECT sip_address.value, chat_message_participant.state_change_time"
" FROM sip_address, chat_message_participant"
......@@ -2035,7 +2010,7 @@ list<MainDb::ParticipantState> MainDb::getChatMessageParticipantsThatHaveReceive
list<MainDb::ParticipantState> result;
for (const auto &row : rows)
result.emplace_back(IdentityAddress(row.get<string>(0)), ChatMessage::State::DeliveredToUser, MainDbPrivate::getTmAsTimeT(row.get<tm>(1)));
result.emplace_back(IdentityAddress(row.get<string>(0)), state, MainDbPrivate::getTmAsTimeT(row.get<tm>(1)));
return result;
};
}
......@@ -2092,19 +2067,7 @@ void MainDb::setChatMessageParticipantState (
) {
L_DB_TRANSACTION {
L_D();
const EventLogPrivate *dEventLog = eventLog->getPrivate();
MainDbKeyPrivate *dEventKey = static_cast<MainDbKey &>(dEventLog->dbKey).getPrivate();
const long long &eventId = dEventKey->storageId;
const long long &participantSipAddressId = d->selectSipAddressId(participantAddress.asString());
int stateInt = static_cast<int>(state);
const tm &stateChangeTm = Utils::getTimeTAsTm(stateChangeTime);
*d->dbSession.getBackendSession() << "UPDATE chat_message_participant SET state = :state,"
" state_change_time = :stateChangeTm"
" WHERE event_id = :eventId AND participant_sip_address_id = :participantSipAddressId",
soci::use(stateInt), soci::use(stateChangeTm), soci::use(eventId), soci::use(participantSipAddressId);
d->setChatMessageParticipantState(eventLog, participantAddress, state, stateChangeTime);
tr.commit();
};
}
......
......@@ -102,14 +102,9 @@ public:
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
std::list<ParticipantState> getChatMessageParticipantsByImdnState (
const std::shared_ptr<EventLog> &eventLog,
ChatMessage::State state
) const;
std::list<ChatMessage::State> getChatMessageParticipantStates (const std::shared_ptr<EventLog> &eventLog) const;
ChatMessage::State getChatMessageParticipantState (
......
......@@ -3089,8 +3089,8 @@ static void imdn_for_group_chat_room (void) {
// 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, 3000));
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);
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDisplayed));
bctbx_list_t *participantsThatReceivedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDeliveredToUser);
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)) {
......@@ -3101,33 +3101,36 @@ static void imdn_for_group_chat_room (void) {
}
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));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDelivered));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateNotDelivered));
// 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, 3000));
bctbx_list_t *participantsThatDisplayedChloeMessage = linphone_chat_message_get_participants_that_have_displayed(chloeMessage);
bctbx_list_t *participantsThatDisplayedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDisplayed);
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);
participantsThatReceivedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDeliveredToUser);
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));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDelivered));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateNotDelivered));
// 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, 3000));
participantsThatDisplayedChloeMessage = linphone_chat_message_get_participants_that_have_displayed(chloeMessage);
participantsThatDisplayedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDisplayed);
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));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDeliveredToUser));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDelivered));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateNotDelivered));
linphone_chat_message_unref(chloeMessage);
......@@ -3303,8 +3306,8 @@ static void imdn_sent_from_db_state (void) {
// 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, 3000));
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);
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDisplayed));
bctbx_list_t *participantsThatReceivedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDeliveredToUser);
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)) {
......@@ -3315,7 +3318,8 @@ static void imdn_sent_from_db_state (void) {
}
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));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDelivered));
BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateNotDelivered));
linphone_chat_message_unref(chloeMessage);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment