mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Merge branch '1779-headless-messages-sent-acked' into 'master'
Expose message delivery state changes to websockets API Closes #1779 See merge request briar/briar!1284
This commit is contained in:
@@ -410,3 +410,39 @@ When the last connection is lost (the contact goes offline), it sends a `Contact
|
||||
"type": "event"
|
||||
}
|
||||
```
|
||||
|
||||
### A message was sent
|
||||
|
||||
When Briar sent a message to a contact, it sends a `MessagesSentEvent`. This is indicated in Briar
|
||||
by showing one tick next to the message.
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"contactId": 1,
|
||||
"messageIds": [
|
||||
"+AIMMgOCPFF8HDEhiEHYjbfKrg7v0G94inKxjvjYzA8="
|
||||
]
|
||||
},
|
||||
"name": "MessagesSentEvent",
|
||||
"type": "event"
|
||||
}
|
||||
```
|
||||
|
||||
### A message was acknowledged
|
||||
|
||||
When a contact acknowledges that they received a message, Briar sends a `MessagesAckedEvent`.
|
||||
This is indicated in Briar by showing two ticks next to the message.
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"contactId": 1,
|
||||
"messageIds": [
|
||||
"+AIMMgOCPFF8HDEhiEHYjbfKrg7v0G94inKxjvjYzA8="
|
||||
]
|
||||
},
|
||||
"name": "MessagesAckedEvent",
|
||||
"type": "event"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -11,6 +11,8 @@ import org.briarproject.bramble.api.db.DatabaseExecutor
|
||||
import org.briarproject.bramble.api.db.NoSuchContactException
|
||||
import org.briarproject.bramble.api.event.Event
|
||||
import org.briarproject.bramble.api.event.EventListener
|
||||
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent
|
||||
import org.briarproject.bramble.api.sync.event.MessagesSentEvent
|
||||
import org.briarproject.bramble.api.system.Clock
|
||||
import org.briarproject.bramble.util.StringUtils.utf8IsTooLong
|
||||
import org.briarproject.briar.api.blog.BlogInvitationRequest
|
||||
@@ -39,6 +41,8 @@ import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
internal const val EVENT_CONVERSATION_MESSAGE = "ConversationMessageReceivedEvent"
|
||||
internal const val EVENT_MESSAGES_ACKED = "MessagesAckedEvent"
|
||||
internal const val EVENT_MESSAGES_SENT = "MessagesSentEvent"
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
@@ -90,6 +94,12 @@ constructor(
|
||||
webSocketController.sendEvent(EVENT_CONVERSATION_MESSAGE, e.output())
|
||||
}
|
||||
}
|
||||
is MessagesSentEvent -> {
|
||||
webSocketController.sendEvent(EVENT_MESSAGES_SENT, e.output())
|
||||
}
|
||||
is MessagesAckedEvent -> {
|
||||
webSocketController.sendEvent(EVENT_MESSAGES_ACKED, e.output())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package org.briarproject.briar.headless.messaging
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId
|
||||
import org.briarproject.bramble.api.sync.MessageId
|
||||
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent
|
||||
import org.briarproject.bramble.api.sync.event.MessagesSentEvent
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader
|
||||
@@ -43,3 +46,15 @@ internal fun PrivateMessage.output(contactId: ContactId, text: String) = JsonDic
|
||||
"groupId" to message.groupId.bytes,
|
||||
"text" to text
|
||||
)
|
||||
|
||||
internal fun MessagesAckedEvent.output() = JsonDict(
|
||||
"contactId" to contactId.int,
|
||||
"messageIds" to messageIds.toJson()
|
||||
)
|
||||
|
||||
internal fun MessagesSentEvent.output() = JsonDict(
|
||||
"contactId" to contactId.int,
|
||||
"messageIds" to messageIds.toJson()
|
||||
)
|
||||
|
||||
internal fun Collection<MessageId>.toJson() = map { it.bytes }
|
||||
|
||||
@@ -10,11 +10,13 @@ import org.briarproject.bramble.api.db.NoSuchContactException
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED
|
||||
import org.briarproject.bramble.api.sync.MessageId
|
||||
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent
|
||||
import org.briarproject.bramble.api.sync.event.MessagesSentEvent
|
||||
import org.briarproject.bramble.test.ImmediateExecutor
|
||||
import org.briarproject.bramble.test.TestUtils.getRandomId
|
||||
import org.briarproject.bramble.util.StringUtils.getRandomString
|
||||
import org.briarproject.briar.api.client.SessionId
|
||||
import org.briarproject.briar.api.conversation.ConversationManager
|
||||
import org.briarproject.briar.api.introduction.IntroductionRequest
|
||||
import org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_TEXT_LENGTH
|
||||
import org.briarproject.briar.api.messaging.MessagingManager
|
||||
@@ -100,6 +102,40 @@ internal class MessagingControllerImplTest : ControllerTest() {
|
||||
testInvalidContactId { controller.list(ctx) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMessagesAckedEvent() {
|
||||
val messageId1 = MessageId(getRandomId())
|
||||
val messageId2 = MessageId(getRandomId())
|
||||
val messageIds = listOf(messageId1, messageId2)
|
||||
val event = MessagesAckedEvent(contact.id, messageIds)
|
||||
|
||||
every {
|
||||
webSocketController.sendEvent(
|
||||
EVENT_MESSAGES_ACKED,
|
||||
event.output()
|
||||
)
|
||||
} just runs
|
||||
|
||||
controller.eventOccurred(event)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMessagesSentEvent() {
|
||||
val messageId1 = MessageId(getRandomId())
|
||||
val messageId2 = MessageId(getRandomId())
|
||||
val messageIds = listOf(messageId1, messageId2)
|
||||
val event = MessagesSentEvent(contact.id, messageIds)
|
||||
|
||||
every {
|
||||
webSocketController.sendEvent(
|
||||
EVENT_MESSAGES_SENT,
|
||||
event.output()
|
||||
)
|
||||
} just runs
|
||||
|
||||
controller.eventOccurred(event)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun listNonexistentContactId() {
|
||||
testNonexistentContactId { controller.list(ctx) }
|
||||
@@ -177,6 +213,43 @@ internal class MessagingControllerImplTest : ControllerTest() {
|
||||
controller.eventOccurred(event)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOutputMessagesAckedEvent() {
|
||||
val messageId1 = MessageId(getRandomId())
|
||||
val messageId2 = MessageId(getRandomId())
|
||||
val messageIds = listOf(messageId1, messageId2)
|
||||
val event = MessagesAckedEvent(contact.id, messageIds)
|
||||
val json = """
|
||||
{
|
||||
"contactId": ${contact.id.int},
|
||||
"messageIds": [
|
||||
${toJson(messageId1.bytes)},
|
||||
${toJson(messageId2.bytes)}
|
||||
]
|
||||
}
|
||||
"""
|
||||
assertJsonEquals(json, event.output())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOutputMessagesSentEvent() {
|
||||
val messageId1 = MessageId(getRandomId())
|
||||
val messageId2 = MessageId(getRandomId())
|
||||
val messageIds = listOf(messageId1, messageId2)
|
||||
val event = MessagesSentEvent(contact.id, messageIds)
|
||||
|
||||
val json = """
|
||||
{
|
||||
"contactId": ${contact.id.int},
|
||||
"messageIds": [
|
||||
${toJson(messageId1.bytes)},
|
||||
${toJson(messageId2.bytes)}
|
||||
]
|
||||
}
|
||||
"""
|
||||
assertJsonEquals(json, event.output())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOutputPrivateMessageHeader() {
|
||||
val json = """
|
||||
|
||||
Reference in New Issue
Block a user