Changeset View
Changeset View
Standalone View
Standalone View
plugins/sms/conversationsdbusinterface.cpp
Show All 16 Lines | |||||
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "conversationsdbusinterface.h" | 21 | #include "conversationsdbusinterface.h" | ||
22 | #include "interfaces/dbusinterfaces.h" | 22 | #include "interfaces/dbusinterfaces.h" | ||
23 | #include "interfaces/conversationmessage.h" | 23 | #include "interfaces/conversationmessage.h" | ||
24 | 24 | | |||
25 | #include "requestconversationworker.h" | ||||
26 | | ||||
25 | #include <QDBusConnection> | 27 | #include <QDBusConnection> | ||
26 | 28 | | |||
27 | #include <core/device.h> | 29 | #include <core/device.h> | ||
28 | #include <core/kdeconnectplugin.h> | 30 | #include <core/kdeconnectplugin.h> | ||
29 | 31 | | |||
30 | Q_LOGGING_CATEGORY(KDECONNECT_CONVERSATIONS, "kdeconnect.conversations") | 32 | Q_LOGGING_CATEGORY(KDECONNECT_CONVERSATIONS, "kdeconnect.conversations") | ||
31 | 33 | | |||
32 | ConversationsDbusInterface::ConversationsDbusInterface(KdeConnectPlugin* plugin) | 34 | ConversationsDbusInterface::ConversationsDbusInterface(KdeConnectPlugin* plugin) | ||
Show All 26 Lines | 53 | for (auto it = m_conversations.cbegin(); it != m_conversations.cend(); ++it) { | |||
59 | } | 61 | } | ||
60 | const QVariantMap& message = (*conversation.crbegin()).toVariant(); | 62 | const QVariantMap& message = (*conversation.crbegin()).toVariant(); | ||
61 | toReturn.append(message); | 63 | toReturn.append(message); | ||
62 | } | 64 | } | ||
63 | 65 | | |||
64 | return toReturn; | 66 | return toReturn; | ||
65 | } | 67 | } | ||
66 | 68 | | |||
67 | void ConversationsDbusInterface::requestConversation(const QString& conversationID, int start, int end) | 69 | void ConversationsDbusInterface::requestConversation(const qint32& conversationID, int start, int end) | ||
68 | { | 70 | { | ||
69 | const auto messagesList = m_conversations[conversationID].values(); | 71 | RequestConversationWorker* worker = new RequestConversationWorker(conversationID, start, end, this); | ||
70 | 72 | connect(worker, &RequestConversationWorker::conversationMessageRead, | |||
71 | if (messagesList.isEmpty()) { | 73 | this, &ConversationsDbusInterface::conversationUpdated, | ||
72 | // Since there are no messages in the conversation, it's likely that it is a junk ID, but go ahead anyway | 74 | Qt::QueuedConnection); | ||
73 | qCWarning(KDECONNECT_CONVERSATIONS) << "Got a conversationID for a conversation with no messages!" << conversationID; | 75 | worker->work(); | ||
74 | } | | |||
75 | | ||||
76 | // TODO: Check local cache before requesting new messages | | |||
77 | // TODO: Make Android interface capable of requesting small window of messages | | |||
78 | m_smsInterface.requestConversation(conversationID); | | |||
79 | | ||||
80 | // Messages are sorted in ascending order of keys, meaning the front of the list has the oldest | | |||
81 | // messages (smallest timestamp number) | | |||
82 | // Therefore, return the end of the list first (most recent messages) | | |||
83 | int i = start; | | |||
84 | for(auto it = messagesList.crbegin() + start; it != messagesList.crend(); ++it) { | | |||
85 | Q_EMIT conversationMessageReceived(it->toVariant(), i); | | |||
86 | i++; | | |||
87 | if (i >= end) { | | |||
88 | break; | | |||
89 | } | | |||
90 | } | | |||
91 | } | 76 | } | ||
apol: Use `m_conversations.value(conversationID)`. Otherwise, if conversationId doesn't exist, it… | |||||
This is actually fixed in D16475 sredman: This is actually fixed in D16475 | |||||
92 | 77 | | |||
93 | void ConversationsDbusInterface::addMessage(const ConversationMessage &message) | 78 | void ConversationsDbusInterface::addMessages(const QList<ConversationMessage> &messages) | ||
94 | { | 79 | { | ||
95 | const QString& threadId = QString::number(message.threadID()); | 80 | QSet<qint32> updatedConversationIDs; | ||
81 | | ||||
82 | for (const auto& message : messages) { | ||||
83 | const qint32& threadId = message.threadID(); | ||||
apol: `messagesList.length() <= end` | |||||
96 | 84 | | |||
97 | if (m_known_messages[threadId].contains(message.uID())) { | 85 | if (m_known_messages[threadId].contains(message.uID())) { | ||
98 | // This message has already been processed. Don't do anything. | 86 | // This message has already been processed. Don't do anything. | ||
99 | return; | 87 | continue; | ||
100 | } | 88 | } | ||
101 | 89 | | |||
90 | updatedConversationIDs.insert(message.threadID()); | ||||
91 | | ||||
102 | // Store the Message in the list corresponding to its thread | 92 | // Store the Message in the list corresponding to its thread | ||
103 | bool newConversation = !m_conversations.contains(threadId); | 93 | bool newConversation = !m_conversations.contains(threadId); | ||
104 | m_conversations[threadId].insert(message.date(), message); | 94 | const auto& threadPosition = m_conversations[threadId].insert(message.date(), message); | ||
105 | m_known_messages[threadId].insert(message.uID()); | 95 | m_known_messages[threadId].insert(message.uID()); | ||
106 | 96 | | |||
97 | // If this message was inserted at the end of the list, it is the latest message in the conversation | ||||
98 | bool latestMessage = threadPosition == m_conversations[threadId].end() - 1; | ||||
99 | | ||||
107 | // Tell the world about what just happened | 100 | // Tell the world about what just happened | ||
108 | if (newConversation) { | 101 | if (newConversation) { | ||
109 | Q_EMIT conversationCreated(message.toVariant()); | 102 | Q_EMIT conversationCreated(message.toVariant()); | ||
110 | } else { | 103 | } else if (latestMessage) { | ||
111 | Q_EMIT conversationUpdated(message.toVariant()); | 104 | Q_EMIT conversationUpdated(message.toVariant()); | ||
112 | } | 105 | } | ||
113 | } | 106 | } | ||
114 | 107 | | |||
108 | waitingForMessagesLock.lock(); | ||||
109 | // Remove the waiting flag for all conversations which we just processed | ||||
110 | conversationsWaitingForMessages.subtract(updatedConversationIDs); | ||||
111 | waitingForMessages.wakeAll(); | ||||
112 | waitingForMessagesLock.unlock(); | ||||
113 | } | ||||
114 | | ||||
115 | void ConversationsDbusInterface::removeMessage(const QString& internalId) | 115 | void ConversationsDbusInterface::removeMessage(const QString& internalId) | ||
116 | { | 116 | { | ||
117 | // TODO: Delete the specified message from our internal structures | 117 | // TODO: Delete the specified message from our internal structures | ||
118 | } | 118 | } | ||
119 | 119 | | |||
120 | void ConversationsDbusInterface::replyToConversation(const QString& conversationID, const QString& message) | 120 | QList<ConversationMessage> ConversationsDbusInterface::getConversation(const qint32& conversationID) const | ||
121 | { | ||||
122 | return m_conversations.value(conversationID).values(); | ||||
123 | } | ||||
124 | | ||||
125 | void ConversationsDbusInterface::updateConversation(const qint32& conversationID) | ||||
126 | { | ||||
127 | waitingForMessagesLock.lock(); | ||||
128 | qCDebug(KDECONNECT_CONVERSATIONS) << "Requesting conversation with ID" << conversationID << "from remote"; | ||||
129 | conversationsWaitingForMessages.insert(conversationID); | ||||
130 | m_smsInterface.requestConversation(conversationID); | ||||
131 | while (conversationsWaitingForMessages.contains(conversationID)) { | ||||
132 | waitingForMessages.wait(&waitingForMessagesLock); | ||||
133 | } | ||||
134 | waitingForMessagesLock.unlock(); | ||||
135 | } | ||||
136 | | ||||
137 | void ConversationsDbusInterface::replyToConversation(const qint32& conversationID, const QString& message) | ||||
121 | { | 138 | { | ||
122 | const auto messagesList = m_conversations[conversationID]; | 139 | const auto messagesList = m_conversations[conversationID]; | ||
123 | if (messagesList.isEmpty()) { | 140 | if (messagesList.isEmpty()) { | ||
124 | // Since there are no messages in the conversation, we can't do anything sensible | 141 | // Since there are no messages in the conversation, we can't do anything sensible | ||
125 | qCWarning(KDECONNECT_CONVERSATIONS) << "Got a conversationID for a conversation with no messages!"; | 142 | qCWarning(KDECONNECT_CONVERSATIONS) << "Got a conversationID for a conversation with no messages!"; | ||
126 | return; | 143 | return; | ||
127 | } | 144 | } | ||
128 | // Caution: | 145 | // Caution: | ||
Show All 17 Lines |
Use m_conversations.value(conversationID). Otherwise, if conversationId doesn't exist, it will create the entry and leave it empty.