diff --git a/packages/moxxmpp/CHANGELOG.md b/packages/moxxmpp/CHANGELOG.md index a68b154..d8ad087 100644 --- a/packages/moxxmpp/CHANGELOG.md +++ b/packages/moxxmpp/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.3.2 +## 0.4.0 - **BREAKING**: Remove `lastResource` from `XmppConnection`'s `connect` method. Instead, set the `StreamManagementNegotiator`'s `resource` attribute instead. Since the resource can only really be restored by stream management, this is no issue. - **BREAKING**: Changed order of parameters of `CryptographicHashManager.hashFromData` @@ -11,6 +11,8 @@ - **BREAKING**: `PubSubManager` and `UserAvatarManager` now use `JID` instead of `String`. - **BREAKING**: `XmppConnection.sendStanza` not only takes a `StanzaDetails` argument. - Sent stanzas are now kept in a queue until sent. +- **BREAKING**: `MessageManager.sendMessage` does not use `MessageDetails` anymore. Instead, use `TypedMap`. +- `MessageManager` now allows registering callbacks for adding data whenever a message is sent. ## 0.3.1 diff --git a/packages/moxxmpp/lib/src/message.dart b/packages/moxxmpp/lib/src/message.dart index 701d8ce..e10dd2e 100644 --- a/packages/moxxmpp/lib/src/message.dart +++ b/packages/moxxmpp/lib/src/message.dart @@ -1,5 +1,4 @@ import 'package:collection/collection.dart'; -import 'package:moxlib/moxlib.dart'; import 'package:moxxmpp/src/events.dart'; import 'package:moxxmpp/src/jid.dart'; import 'package:moxxmpp/src/managers/base.dart'; @@ -15,19 +14,22 @@ import 'package:moxxmpp/src/xeps/xep_0066.dart'; import 'package:moxxmpp/src/xeps/xep_0085.dart'; import 'package:moxxmpp/src/xeps/xep_0184.dart'; import 'package:moxxmpp/src/xeps/xep_0280.dart'; -import 'package:moxxmpp/src/xeps/xep_0308.dart'; import 'package:moxxmpp/src/xeps/xep_0333.dart'; import 'package:moxxmpp/src/xeps/xep_0334.dart'; import 'package:moxxmpp/src/xeps/xep_0359.dart'; import 'package:moxxmpp/src/xeps/xep_0385.dart'; import 'package:moxxmpp/src/xeps/xep_0424.dart'; import 'package:moxxmpp/src/xeps/xep_0444.dart'; -import 'package:moxxmpp/src/xeps/xep_0446.dart'; import 'package:moxxmpp/src/xeps/xep_0447.dart'; -import 'package:moxxmpp/src/xeps/xep_0448.dart'; import 'package:moxxmpp/src/xeps/xep_0449.dart'; import 'package:moxxmpp/src/xeps/xep_0461.dart'; +/// A callback that is called whenever a message is sent using +/// [MessageManager.sendMessage]. The input the typed map that is passed to +/// sendMessage. +typedef MessageSendingCallback = List Function(TypedMap); + +/// The raw content of the element. class MessageBodyData { const MessageBodyData(this.body); @@ -42,6 +44,7 @@ class MessageBodyData { } } +/// The id attribute of the message stanza. class MessageIdData { const MessageIdData(this.id); @@ -49,60 +52,6 @@ class MessageIdData { final String id; } -typedef MessageSendingCallback = List Function(TypedMap); - -/// Data used to build a message stanza. -/// -/// [setOOBFallbackBody] indicates, when using SFS, whether a OOB fallback should be -/// added. This is recommended when sharing files but may cause issues when the message -/// stanza should include a SFS element without any fallbacks. -class MessageDetails { - const MessageDetails({ - required this.to, - this.body, - this.requestDeliveryReceipt = false, - this.requestChatMarkers = true, - this.id, - this.originId, - this.quoteBody, - this.quoteId, - this.quoteFrom, - this.chatState, - this.sfs, - this.fun, - this.funReplacement, - this.funCancellation, - this.shouldEncrypt = false, - this.messageRetraction, - this.lastMessageCorrectionId, - this.messageReactions, - this.messageProcessingHints, - this.stickerPackId, - this.setOOBFallbackBody = true, - }); - final String to; - final String? body; - final bool requestDeliveryReceipt; - final bool requestChatMarkers; - final String? id; - final String? originId; - final String? quoteBody; - final String? quoteId; - final String? quoteFrom; - final ChatState? chatState; - final StatelessFileSharingData? sfs; - final FileMetadataData? fun; - final String? funReplacement; - final String? funCancellation; - final bool shouldEncrypt; - final MessageRetractionData? messageRetraction; - final String? lastMessageCorrectionId; - final MessageReactions? messageReactions; - final String? stickerPackId; - final List? messageProcessingHints; - final bool setOOBFallbackBody; -} - class MessageManager extends XmppManagerBase { MessageManager() : super(messageManager); @@ -179,7 +128,9 @@ class MessageManager extends XmppManagerBase { return state..done = true; } - Future sendMessage2(JID to, TypedMap extensions) async { + /// Send an unawaitable message to [to]. [extensions] is a typed map that contains + /// data for building the message. + Future sendMessage(JID to, TypedMap extensions) async { await getAttributes().sendStanza( StanzaDetails( Stanza.message( @@ -196,194 +147,6 @@ class MessageManager extends XmppManagerBase { ); } - /// Send a message to to with the content body. If deliveryRequest is true, then - /// the message will also request a delivery receipt from the receiver. - /// If id is non-null, then it will be the id of the message stanza. - /// element to this id. If originId is non-null, then it will create an "origin-id" - /// child in the message stanza and set its id to originId. - Future sendMessage(MessageDetails details) async { - assert( - implies( - details.quoteBody != null, - details.quoteFrom != null && details.quoteId != null, - ), - 'When quoting a message, then quoteFrom and quoteId must also be non-null', - ); - - final stanza = Stanza.message( - to: details.to, - type: 'chat', - id: details.id, - children: [], - ); - - if (details.quoteBody != null) { - final quote = QuoteData.fromBodies(details.quoteBody!, details.body!); - - stanza - ..addChild( - XMLNode(tag: 'body', text: quote.body), - ) - ..addChild( - XMLNode.xmlns( - tag: 'reply', - xmlns: replyXmlns, - attributes: {'to': details.quoteFrom!, 'id': details.quoteId!}, - ), - ) - ..addChild( - XMLNode.xmlns( - tag: 'fallback', - xmlns: fallbackXmlns, - attributes: {'for': replyXmlns}, - children: [ - XMLNode( - tag: 'body', - attributes: { - 'start': '0', - 'end': '${quote.fallbackLength}', - }, - ) - ], - ), - ); - } else { - var body = details.body; - if (details.sfs != null && details.setOOBFallbackBody) { - // TODO(Unknown): Maybe find a better solution - final firstSource = details.sfs!.sources.first; - if (firstSource is StatelessFileSharingUrlSource) { - body = firstSource.url; - } else if (firstSource is StatelessFileSharingEncryptedSource) { - body = firstSource.source.url; - } - } else if (details.messageRetraction?.fallback != null) { - body = details.messageRetraction!.fallback; - } - - if (body != null) { - stanza.addChild( - XMLNode(tag: 'body', text: body), - ); - } - } - - // if (details.requestDeliveryReceipt) { - // stanza.addChild(makeMessageDeliveryRequest()); - // } - if (details.requestChatMarkers) { - stanza.addChild(makeChatMarkerMarkable()); - } - if (details.originId != null) { - stanza.addChild(StableIdData(details.originId, null).toOriginIdElement()); - } - - if (details.sfs != null) { - stanza.addChild(details.sfs!.toXML()); - - final source = details.sfs!.sources.first; - if (source is StatelessFileSharingUrlSource && - details.setOOBFallbackBody) { - // SFS recommends OOB as a fallback - stanza.addChild(OOBData(source.url, null).toXML()); - } - } - - if (details.chatState != null) { - stanza.addChild( - details.chatState!.toXML(), - ); - } - - if (details.fun != null) { - stanza.addChild( - XMLNode.xmlns( - tag: 'file-upload', - xmlns: fileUploadNotificationXmlns, - children: [ - details.fun!.toXML(), - ], - ), - ); - } - - if (details.funReplacement != null) { - stanza.addChild( - XMLNode.xmlns( - tag: 'replaces', - xmlns: fileUploadNotificationXmlns, - attributes: { - 'id': details.funReplacement!, - }, - ), - ); - } - - if (details.messageRetraction != null) { - stanza.addChild( - XMLNode.xmlns( - tag: 'apply-to', - xmlns: fasteningXmlns, - attributes: { - 'id': details.messageRetraction!.id, - }, - children: [ - XMLNode.xmlns( - tag: 'retract', - xmlns: messageRetractionXmlns, - ), - ], - ), - ); - - if (details.messageRetraction!.fallback != null) { - stanza.addChild( - XMLNode.xmlns( - tag: 'fallback', - xmlns: fallbackIndicationXmlns, - ), - ); - } - } - - if (details.lastMessageCorrectionId != null) { - stanza.addChild( - LastMessageCorrectionData( - details.lastMessageCorrectionId!, - ).toXML(), - ); - } - - if (details.messageReactions != null) { - stanza.addChild(details.messageReactions!.toXML()); - } - - if (details.messageProcessingHints != null) { - for (final hint in details.messageProcessingHints!) { - stanza.addChild(hint.toXML()); - } - } - - if (details.stickerPackId != null) { - stanza.addChild( - XMLNode.xmlns( - tag: 'sticker', - xmlns: stickersXmlns, - attributes: { - 'pack': details.stickerPackId!, - }, - ), - ); - } - - await getAttributes().sendStanza( - StanzaDetails( - stanza, - awaitable: false, - ), - ); - } - List _messageSendingCallback(TypedMap extensions) { if (extensions.get() != null) { return []; diff --git a/packages/moxxmpp/test/xeps/xep_0449_test.dart b/packages/moxxmpp/test/xeps/xep_0449_test.dart index c58d972..69c777d 100644 --- a/packages/moxxmpp/test/xeps/xep_0449_test.dart +++ b/packages/moxxmpp/test/xeps/xep_0449_test.dart @@ -268,7 +268,7 @@ void main() { SFSManager(), ]); - await manager.sendMessage2( + await manager.sendMessage( JID.fromString('user@example.org'), TypedMap() ..set(