diff --git a/include/linphone/api/c-chat-message.h b/include/linphone/api/c-chat-message.h index b795a0b06..1b66980bf 100644 --- a/include/linphone/api/c-chat-message.h +++ b/include/linphone/api/c-chat-message.h @@ -167,6 +167,21 @@ LINPHONE_PUBLIC const char * linphone_chat_message_get_file_transfer_filepath(Li // ============================================================================= +/** + * Get if a chat message is to be stored. + * @param[in] message LinphoneChatMessage object + * @return Whether or not the message is to be stored + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_get_to_be_stored(const LinphoneChatMessage *message); + +/** + * Set if a chat message is to be stored. + * This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml. + * @param[in] message LinphoneChatMessage object + * @param[in] to_be_stored Whether or not the chat message is to be stored + */ +LINPHONE_PUBLIC void linphone_chat_message_set_to_be_stored(LinphoneChatMessage *message, bool_t to_be_stored); + LINPHONE_PUBLIC unsigned int linphone_chat_message_store(LinphoneChatMessage *msg); /** diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 4b9a2d607..da453b39c 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -177,6 +177,14 @@ const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChat return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getErrorInfo(); } +bool_t linphone_chat_message_get_to_be_stored(const LinphoneChatMessage *message) { + return L_GET_CPP_PTR_FROM_C_OBJECT(message)->getToBeStored(); +} + +void linphone_chat_message_set_to_be_stored(LinphoneChatMessage *message, bool_t to_be_stored) { + L_GET_CPP_PTR_FROM_C_OBJECT(message)->setToBeStored(!!to_be_stored); +} + // ============================================================================= // Methods // ============================================================================= diff --git a/src/chat/chat-message/chat-message-p.h b/src/chat/chat-message/chat-message-p.h index f446525c3..0191349e8 100644 --- a/src/chat/chat-message/chat-message-p.h +++ b/src/chat/chat-message/chat-message-p.h @@ -59,11 +59,11 @@ public: void setDirection (ChatMessage::Direction dir); - void setState(ChatMessage::State state, bool force = false, bool storeInDb = true); + void setState (ChatMessage::State state, bool force = false); - void setTime(time_t time); + void setTime (time_t time); - void setIsReadOnly(bool readOnly); + void setIsReadOnly (bool readOnly); void setImdnMessageId (const std::string &imdnMessageId); @@ -75,20 +75,20 @@ public: this->toAddress = toAddress; } - belle_http_request_t *getHttpRequest() const; - void setHttpRequest(belle_http_request_t *request); + belle_http_request_t *getHttpRequest () const; + void setHttpRequest (belle_http_request_t *request); - SalOp *getSalOp() const; - void setSalOp(SalOp *op); + SalOp *getSalOp () const; + void setSalOp (SalOp *op); - SalCustomHeader *getSalCustomHeaders() const; - void setSalCustomHeaders(SalCustomHeader *headers); + SalCustomHeader *getSalCustomHeaders () const; + void setSalCustomHeaders (SalCustomHeader *headers); - void addSalCustomHeader(const std::string& name, const std::string& value); - void removeSalCustomHeader(const std::string& name); - std::string getSalCustomHeaderValue(const std::string& name); + void addSalCustomHeader (const std::string& name, const std::string& value); + void removeSalCustomHeader (const std::string& name); + std::string getSalCustomHeaderValue (const std::string& name); - void loadFileTransferUrlFromBodyToContent(); + void loadFileTransferUrlFromBodyToContent (); void setChatRoom (const std::shared_ptr &chatRoom); @@ -96,11 +96,11 @@ public: // Deprecated methods only used for C wrapper, to be removed some day... // ----------------------------------------------------------------------------- - const ContentType &getContentType(); - void setContentType(const ContentType &contentType); + const ContentType &getContentType (); + void setContentType (const ContentType &contentType); - const std::string &getText(); - void setText(const std::string &text); + const std::string &getText (); + void setText (const std::string &text); const std::string &getFileTransferFilepath () const; void setFileTransferFilepath (const std::string &path); @@ -110,23 +110,25 @@ public: const std::string &getExternalBodyUrl () const; - bool hasTextContent() const; - const Content* getTextContent() const; + bool hasTextContent () const; + const Content* getTextContent () const; - bool hasFileTransferContent() const; - const Content* getFileTransferContent() const; + bool hasFileTransferContent () const; + const Content* getFileTransferContent () const; - LinphoneContent *getFileTransferInformation() const; - void setFileTransferInformation(const LinphoneContent *content); + LinphoneContent *getFileTransferInformation () const; + void setFileTransferInformation (const LinphoneContent *content); bool downloadFile (); - void sendImdn(Imdn::Type imdnType, LinphoneReason reason); + void sendImdn (Imdn::Type imdnType, LinphoneReason reason); - LinphoneReason receive(); - void send(); + void notifyReceiving (); + LinphoneReason receive (); + void send (); - void store(); + void storeInDb (); + void updateInDb (); private: // TODO: Clean attributes. @@ -166,6 +168,8 @@ private: ChatMessage::State state = ChatMessage::State::Idle; ChatMessage::Direction direction = ChatMessage::Direction::Incoming; + bool toBeStored = true; + L_DECLARE_PUBLIC(ChatMessage); }; diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index cd6bf76e6..d739ada34 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -63,7 +63,7 @@ void ChatMessagePrivate::setIsReadOnly (bool readOnly) { isReadOnly = readOnly; } -void ChatMessagePrivate::setState (ChatMessage::State s, bool force, bool storeInDb) { +void ChatMessagePrivate::setState (ChatMessage::State s, bool force) { L_Q(); if (force) @@ -98,9 +98,7 @@ void ChatMessagePrivate::setState (ChatMessage::State s, bool force, bool storeI if (cbs && linphone_chat_message_cbs_get_msg_state_changed(cbs)) linphone_chat_message_cbs_get_msg_state_changed(cbs)(msg, linphone_chat_message_get_state(msg)); - if (storeInDb) { - store(); - } + updateInDb(); } belle_http_request_t *ChatMessagePrivate::getHttpRequest () const { @@ -205,7 +203,7 @@ void ChatMessagePrivate::setAppdata (const string &data) { break; } } - store(); + updateInDb(); } const string &ChatMessagePrivate::getExternalBodyUrl () const { @@ -381,6 +379,29 @@ static void forceUtf8Content (Content &content) { L_END_LOG_EXCEPTION } +void ChatMessagePrivate::notifyReceiving () { + L_Q(); + + if ((getContentType() == ContentType::Imdn) || (getContentType() == ContentType::ImIsComposing)) + return; + + LinphoneChatRoom *chatRoom = L_GET_C_BACK_PTR(q->getChatRoom()); + LinphoneChatRoomCbs *cbs = linphone_chat_room_get_callbacks(chatRoom); + LinphoneChatRoomCbsParticipantAddedCb cb = linphone_chat_room_cbs_get_chat_message_received(cbs); + shared_ptr event = make_shared( + ::time(nullptr), q->getSharedFromThis() + ); + if (cb) + cb(chatRoom, L_GET_C_BACK_PTR(event)); + // Legacy + q->getChatRoom()->getPrivate()->notifyChatMessageReceived(q->getSharedFromThis()); + + if (toBeStored) + storeInDb(); + + q->sendDeliveryNotification(LinphoneReasonNone); +} + LinphoneReason ChatMessagePrivate::receive () { L_Q(); int errorCode = 0; @@ -389,8 +410,6 @@ LinphoneReason ChatMessagePrivate::receive () { shared_ptr core = q->getCore(); shared_ptr chatRoom = q->getChatRoom(); - setState(ChatMessage::State::Delivered, false, false); // Wait for decryption and CPIM to reveal the real message to know if it must be stored or not - // --------------------------------------- // Start of message modification // --------------------------------------- @@ -451,6 +470,8 @@ LinphoneReason ChatMessagePrivate::receive () { // End of message modification // --------------------------------------- + setState(ChatMessage::State::Delivered, false); + if (errorCode <= 0) { bool foundSupportContentType = false; for (Content *c : contents) { @@ -482,7 +503,8 @@ LinphoneReason ChatMessagePrivate::receive () { return reason; } - store(); + if ((getContentType() == ContentType::ImIsComposing) || (getContentType() == ContentType::Imdn)) + toBeStored = false; return reason; } @@ -493,6 +515,8 @@ void ChatMessagePrivate::send () { LinphoneCall *lcall = nullptr; int errorCode = 0; + storeInDb(); + if ((currentSendStep & ChatMessagePrivate::Step::FileUpload) == ChatMessagePrivate::Step::FileUpload) { lInfo() << "File upload step already done, skipping"; } else { @@ -634,8 +658,6 @@ void ChatMessagePrivate::send () { if (imdnId.empty()) setImdnMessageId(op->get_call_id()); /* must be known at that time */ - //store(); // Store will be done right below in the setState(InProgress) - if (lcall && linphone_call_get_op(lcall) == op) { /* In this case, chat delivery status is not notified, so unrefing chat message right now */ /* Might be better fixed by delivering status, but too costly for now */ @@ -649,43 +671,17 @@ void ChatMessagePrivate::send () { } } -void ChatMessagePrivate::store() { +void ChatMessagePrivate::storeInDb () { L_Q(); // TODO: store message in the future if (linphone_core_conference_server_enabled(q->getCore()->getCCore())) return; - bool messageToBeStored = true; - for (Content *c : contents) { - ContentType contentType = c->getContentType(); - if (contentType == ContentType::Imdn || contentType == ContentType::ImIsComposing) { - messageToBeStored = false; - break; - } - } - if (!messageToBeStored) { - return; - } - - unique_ptr &mainDb = q->getChatRoom()->getCore()->getPrivate()->mainDb; if (dbKey.isValid()) { - shared_ptr eventLog = mainDb->getEventFromKey(dbKey); - mainDb->updateEvent(eventLog); - - if (direction == ChatMessage::Direction::Incoming) { - if (!hasFileTransferContent()) { - // Incoming message doesn't have any download waiting anymore, we can remove it's event from the transients - q->getChatRoom()->getPrivate()->removeTransientEvent(eventLog); - } - } else { - if (state == ChatMessage::State::Delivered || state == ChatMessage::State::NotDelivered) { - // Once message has reached this state it won't change anymore so we can remove the event from the transients - q->getChatRoom()->getPrivate()->removeTransientEvent(eventLog); - } - } + updateInDb(); } else { shared_ptr eventLog = make_shared(time, q->getSharedFromThis()); - mainDb->addEvent(eventLog); + q->getChatRoom()->getCore()->getPrivate()->mainDb->addEvent(eventLog); if (direction == ChatMessage::Direction::Incoming) { if (hasFileTransferContent()) { @@ -699,6 +695,29 @@ void ChatMessagePrivate::store() { } } +void ChatMessagePrivate::updateInDb () { + L_Q(); + + if (!dbKey.isValid()) + return; + + unique_ptr &mainDb = q->getChatRoom()->getCore()->getPrivate()->mainDb; + shared_ptr eventLog = mainDb->getEventFromKey(dbKey); + mainDb->updateEvent(eventLog); + + if (direction == ChatMessage::Direction::Incoming) { + if (!hasFileTransferContent()) { + // Incoming message doesn't have any download waiting anymore, we can remove it's event from the transients + q->getChatRoom()->getPrivate()->removeTransientEvent(eventLog); + } + } else { + if (state == ChatMessage::State::Delivered || state == ChatMessage::State::NotDelivered) { + // Once message has reached this state it won't change anymore so we can remove the event from the transients + q->getChatRoom()->getPrivate()->removeTransientEvent(eventLog); + } + } +} + // ----------------------------------------------------------------------------- ChatMessage::ChatMessage (const shared_ptr &chatRoom, ChatMessage::Direction direction) : @@ -799,6 +818,16 @@ const IdentityAddress &ChatMessage::getToAddress () const { return d->toAddress; } +bool ChatMessage::getToBeStored () const { + L_D(); + return d->toBeStored; +} + +void ChatMessage::setToBeStored (bool value) { + L_D(); + d->toBeStored = value; +} + // ----------------------------------------------------------------------------- const LinphoneErrorInfo *ChatMessage::getErrorInfo () const { diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index d27d4b555..af7623b77 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -90,6 +90,9 @@ public: bool isRead () const; bool isReadOnly () const; + bool getToBeStored () const; + void setToBeStored (bool value); + const std::list &getContents () const; void addContent (Content &content); void removeContent (const Content &content); diff --git a/src/chat/chat-room/abstract-chat-room-p.h b/src/chat/chat-room/abstract-chat-room-p.h index 439fc4f13..5577122ec 100644 --- a/src/chat/chat-room/abstract-chat-room-p.h +++ b/src/chat/chat-room/abstract-chat-room-p.h @@ -45,6 +45,7 @@ public: virtual void addTransientEvent (const std::shared_ptr &eventLog) = 0; virtual void removeTransientEvent (const std::shared_ptr &eventLog) = 0; + virtual void notifyChatMessageReceived (const std::shared_ptr &chatMessage) = 0; virtual void notifyUndecryptableChatMessageReceived (const std::shared_ptr &chatMessage) = 0; virtual LinphoneReason onSipMessageReceived (SalOp *op, const SalMessage *message) = 0; diff --git a/src/chat/chat-room/chat-room-p.h b/src/chat/chat-room/chat-room-p.h index 8f76557b2..dcb22bb92 100644 --- a/src/chat/chat-room/chat-room-p.h +++ b/src/chat/chat-room/chat-room-p.h @@ -52,7 +52,7 @@ public: std::shared_ptr createChatMessage (ChatMessage::Direction direction); std::list> findChatMessages (const std::string &messageId) const; - void notifyChatMessageReceived (const std::shared_ptr &chatMessage); + void notifyChatMessageReceived (const std::shared_ptr &chatMessage) override; void notifyIsComposingReceived (const Address &remoteAddress, bool isComposing); void notifyStateChanged (); void notifyUndecryptableChatMessageReceived (const std::shared_ptr &chatMessage) override; diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index 346e370dd..0a7678573 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -244,24 +244,10 @@ end: } void ChatRoomPrivate::onChatMessageReceived (const shared_ptr &chatMessage) { - L_Q(); - - ContentType contentType = chatMessage->getPrivate()->getContentType(); - if (contentType != ContentType::Imdn && contentType != ContentType::ImIsComposing) { - LinphoneChatRoom *chatRoom = L_GET_C_BACK_PTR(q); - LinphoneChatRoomCbs *cbs = linphone_chat_room_get_callbacks(chatRoom); - LinphoneChatRoomCbsParticipantAddedCb cb = linphone_chat_room_cbs_get_chat_message_received(cbs); - shared_ptr event = make_shared(time(nullptr), chatMessage); - if (cb) - cb(chatRoom, L_GET_C_BACK_PTR(event)); - // Legacy - notifyChatMessageReceived(chatMessage); - - const IdentityAddress &fromAddress = chatMessage->getFromAddress(); - isComposingHandler->stopRemoteRefreshTimer(fromAddress.asString()); - notifyIsComposingReceived(fromAddress, false); - chatMessage->sendDeliveryNotification(LinphoneReasonNone); - } + const IdentityAddress &fromAddress = chatMessage->getFromAddress(); + isComposingHandler->stopRemoteRefreshTimer(fromAddress.asString()); + notifyIsComposingReceived(fromAddress, false); + chatMessage->getPrivate()->notifyReceiving(); } void ChatRoomPrivate::onImdnReceived (const string &text) { diff --git a/src/chat/chat-room/proxy-chat-room-p.h b/src/chat/chat-room/proxy-chat-room-p.h index 0675ffa2b..9559c31c4 100644 --- a/src/chat/chat-room/proxy-chat-room-p.h +++ b/src/chat/chat-room/proxy-chat-room-p.h @@ -52,6 +52,10 @@ public: chatRoom->getPrivate()->removeTransientEvent(eventLog); } + inline void notifyChatMessageReceived (const std::shared_ptr &chatMessage) override { + chatRoom->getPrivate()->notifyChatMessageReceived(chatMessage); + } + inline void notifyUndecryptableChatMessageReceived (const std::shared_ptr &chatMessage) override { chatRoom->getPrivate()->notifyUndecryptableChatMessageReceived(chatMessage); } diff --git a/src/chat/chat-room/real-time-text-chat-room.cpp b/src/chat/chat-room/real-time-text-chat-room.cpp index 0122e086b..f12e120b3 100644 --- a/src/chat/chat-room/real-time-text-chat-room.cpp +++ b/src/chat/chat-room/real-time-text-chat-room.cpp @@ -70,7 +70,7 @@ void RealTimeTextChatRoomPrivate::realtimeTextReceived (uint32_t character, Linp pendingMessage->getPrivate()->setDirection(ChatMessage::Direction::Incoming); if (lp_config_get_int(linphone_core_get_config(cCore), "misc", "store_rtt_messages", 1) == 1) - pendingMessage->getPrivate()->store(); + pendingMessage->getPrivate()->storeInDb(); onChatMessageReceived(pendingMessage); pendingMessage = nullptr;