feat(xep): Refactor sendMessage to allow groupchat
Signed-off-by: Ikjot Singh Dhody <ikjotsd@gmail.com>
This commit is contained in:
		
							parent
							
								
									64a8de6caa
								
							
						
					
					
						commit
						05c41d3185
					
				| @ -48,6 +48,8 @@ export 'package:moxxmpp/src/xeps/xep_0030/errors.dart'; | |||||||
| export 'package:moxxmpp/src/xeps/xep_0030/helpers.dart'; | export 'package:moxxmpp/src/xeps/xep_0030/helpers.dart'; | ||||||
| export 'package:moxxmpp/src/xeps/xep_0030/types.dart'; | export 'package:moxxmpp/src/xeps/xep_0030/types.dart'; | ||||||
| export 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart'; | export 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart'; | ||||||
|  | export 'package:moxxmpp/src/xeps/xep_0045/errors.dart'; | ||||||
|  | export 'package:moxxmpp/src/xeps/xep_0045/types.dart'; | ||||||
| export 'package:moxxmpp/src/xeps/xep_0045/xep_0045.dart'; | export 'package:moxxmpp/src/xeps/xep_0045/xep_0045.dart'; | ||||||
| export 'package:moxxmpp/src/xeps/xep_0054.dart'; | export 'package:moxxmpp/src/xeps/xep_0054.dart'; | ||||||
| export 'package:moxxmpp/src/xeps/xep_0060/errors.dart'; | export 'package:moxxmpp/src/xeps/xep_0060/errors.dart'; | ||||||
|  | |||||||
| @ -1,89 +1,72 @@ | |||||||
| import 'package:moxlib/moxlib.dart'; | import 'package:collection/collection.dart'; | ||||||
| import 'package:moxxmpp/src/events.dart'; | import 'package:moxxmpp/src/events.dart'; | ||||||
| import 'package:moxxmpp/src/jid.dart'; | import 'package:moxxmpp/src/jid.dart'; | ||||||
| import 'package:moxxmpp/src/managers/base.dart'; | import 'package:moxxmpp/src/managers/base.dart'; | ||||||
| import 'package:moxxmpp/src/managers/data.dart'; | import 'package:moxxmpp/src/managers/data.dart'; | ||||||
| import 'package:moxxmpp/src/managers/handlers.dart'; | import 'package:moxxmpp/src/managers/handlers.dart'; | ||||||
| import 'package:moxxmpp/src/managers/namespaces.dart'; | import 'package:moxxmpp/src/managers/namespaces.dart'; | ||||||
| import 'package:moxxmpp/src/namespaces.dart'; |  | ||||||
| import 'package:moxxmpp/src/stanza.dart'; | import 'package:moxxmpp/src/stanza.dart'; | ||||||
| import 'package:moxxmpp/src/stringxml.dart'; | import 'package:moxxmpp/src/stringxml.dart'; | ||||||
| import 'package:moxxmpp/src/xeps/staging/file_upload_notification.dart'; | import 'package:moxxmpp/src/util/typed_map.dart'; | ||||||
|  | import 'package:moxxmpp/src/xeps/xep_0045/xep_0045.dart'; | ||||||
| import 'package:moxxmpp/src/xeps/xep_0066.dart'; | 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_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_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_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'; | import 'package:moxxmpp/src/xeps/xep_0461.dart'; | ||||||
| 
 | 
 | ||||||
| /// Data used to build a message stanza. | /// A callback that is called whenever a message is sent using | ||||||
| /// | /// [MessageManager.sendMessage]. The input the typed map that is passed to | ||||||
| /// [setOOBFallbackBody] indicates, when using SFS, whether a OOB fallback should be | /// sendMessage. | ||||||
| /// added. This is recommended when sharing files but may cause issues when the message | typedef MessageSendingCallback = List<XMLNode> Function( | ||||||
| /// stanza should include a SFS element without any fallbacks. |   TypedMap<StanzaHandlerExtension>, | ||||||
| class MessageDetails { | ); | ||||||
|   const MessageDetails({ | 
 | ||||||
|     required this.to, | /// The raw content of the <body /> element. | ||||||
|     this.body, | class MessageBodyData implements StanzaHandlerExtension { | ||||||
|     this.requestDeliveryReceipt = false, |   const MessageBodyData(this.body); | ||||||
|     this.requestChatMarkers = true, | 
 | ||||||
|     this.id, |   /// The content of the <body /> element. | ||||||
|     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 String? body; | ||||||
|   final bool requestDeliveryReceipt; | 
 | ||||||
|   final bool requestChatMarkers; |   XMLNode toXML() { | ||||||
|   final String? id; |     return XMLNode( | ||||||
|   final String? originId; |       tag: 'body', | ||||||
|   final String? quoteBody; |       text: body, | ||||||
|   final String? quoteId; |     ); | ||||||
|   final String? quoteFrom; |   } | ||||||
|   final ChatState? chatState; | } | ||||||
|   final StatelessFileSharingData? sfs; | 
 | ||||||
|   final FileMetadataData? fun; | /// The id attribute of the message stanza. | ||||||
|   final String? funReplacement; | class MessageIdData implements StanzaHandlerExtension { | ||||||
|   final String? funCancellation; |   const MessageIdData(this.id); | ||||||
|   final bool shouldEncrypt; | 
 | ||||||
|   final MessageRetractionData? messageRetraction; |   /// The id attribute of the stanza. | ||||||
|   final String? lastMessageCorrectionId; |   final String id; | ||||||
|   final MessageReactions? messageReactions; |  | ||||||
|   final String? stickerPackId; |  | ||||||
|   final List<MessageProcessingHint>? messageProcessingHints; |  | ||||||
|   final bool setOOBFallbackBody; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class MessageManager extends XmppManagerBase { | class MessageManager extends XmppManagerBase { | ||||||
|   MessageManager() : super(messageManager); |   MessageManager() : super(messageManager); | ||||||
| 
 | 
 | ||||||
|  |   /// The priority of the message handler. If a handler should run before this one, | ||||||
|  |   /// which emits the [MessageEvent] event and terminates processing, make sure it | ||||||
|  |   /// has a priority greater than [messageHandlerPriority]. | ||||||
|  |   static int messageHandlerPriority = -100; | ||||||
|  | 
 | ||||||
|  |   /// A list of callbacks that are called when a message is sent in order to add | ||||||
|  |   /// appropriate child elements. | ||||||
|  |   final List<MessageSendingCallback> _messageSendingCallbacks = | ||||||
|  |       List<MessageSendingCallback>.empty(growable: true); | ||||||
|  | 
 | ||||||
|  |   void registerMessageSendingCallback(MessageSendingCallback callback) { | ||||||
|  |     _messageSendingCallbacks.add(callback); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   List<StanzaHandler> getIncomingStanzaHandlers() => [ |   List<StanzaHandler> getIncomingStanzaHandlers() => [ | ||||||
|         StanzaHandler( |         StanzaHandler( | ||||||
|           stanzaTag: 'message', |           stanzaTag: 'message', | ||||||
|           callback: _onMessage, |           callback: _onMessage, | ||||||
|           priority: -100, |           priority: messageHandlerPriority, | ||||||
|         ) |         ) | ||||||
|       ]; |       ]; | ||||||
| 
 | 
 | ||||||
| @ -94,237 +77,72 @@ class MessageManager extends XmppManagerBase { | |||||||
|     Stanza _, |     Stanza _, | ||||||
|     StanzaHandlerData state, |     StanzaHandlerData state, | ||||||
|   ) async { |   ) async { | ||||||
|     final message = state.stanza; |  | ||||||
|     final body = message.firstTag('body'); |  | ||||||
| 
 |  | ||||||
|     final hints = List<MessageProcessingHint>.empty(growable: true); |  | ||||||
|     for (final element |  | ||||||
|         in message.findTagsByXmlns(messageProcessingHintsXmlns)) { |  | ||||||
|       hints.add(messageProcessingHintFromXml(element)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     getAttributes().sendEvent( |     getAttributes().sendEvent( | ||||||
|       MessageEvent( |       MessageEvent( | ||||||
|         body: body != null ? body.innerText() : '', |         JID.fromString(state.stanza.attributes['from']! as String), | ||||||
|         fromJid: JID.fromString(message.attributes['from']! as String), |         JID.fromString(state.stanza.attributes['to']! as String), | ||||||
|         toJid: JID.fromString(message.attributes['to']! as String), |         state.stanza.attributes['id']! as String, | ||||||
|         sid: message.attributes['id']! as String, |         state.encrypted, | ||||||
|         stanzaId: state.stableId ?? const StableStanzaId(), |         state.extensions, | ||||||
|         isCarbon: state.isCarbon, |         type: state.stanza.attributes['type'] as String?, | ||||||
|         deliveryReceiptRequested: state.deliveryReceiptRequested, |         error: StanzaError.fromStanza(state.stanza), | ||||||
|         isMarkable: state.isMarkable, |         encryptionError: state.encryptionError, | ||||||
|         type: message.attributes['type'] as String?, |  | ||||||
|         oob: state.oob, |  | ||||||
|         sfs: state.sfs, |  | ||||||
|         sims: state.sims, |  | ||||||
|         reply: state.reply, |  | ||||||
|         chatState: state.chatState, |  | ||||||
|         fun: state.fun, |  | ||||||
|         funReplacement: state.funReplacement, |  | ||||||
|         funCancellation: state.funCancellation, |  | ||||||
|         encrypted: state.encrypted, |  | ||||||
|         messageRetraction: state.messageRetraction, |  | ||||||
|         messageCorrectionId: state.lastMessageCorrectionSid, |  | ||||||
|         messageReactions: state.messageReactions, |  | ||||||
|         messageProcessingHints: hints.isEmpty ? null : hints, |  | ||||||
|         stickerPackId: state.stickerPackId, |  | ||||||
|         other: state.other, |  | ||||||
|         error: StanzaError.fromStanza(message), |  | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     return state.copyWith(done: true); |     return state..done = true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /// Send a message to to with the content body. If deliveryRequest is true, then |   /// Send an unawaitable message to [to]. [extensions] is a typed map that contains | ||||||
|   /// the message will also request a delivery receipt from the receiver. |   /// data for building the message. | ||||||
|   /// If id is non-null, then it will be the id of the message stanza. |   Future<void> sendMessage( | ||||||
|   /// element to this id. If originId is non-null, then it will create an "origin-id" |     JID to, | ||||||
|   /// child in the message stanza and set its id to originId. |     TypedMap<StanzaHandlerExtension> extensions, | ||||||
|   void sendMessage(MessageDetails details) { |   ) async { | ||||||
|     assert( |     await getAttributes().sendStanza( | ||||||
|       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: <String, String>{ |  | ||||||
|                   '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(makeOriginIdElement(details.originId!)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     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(constructOOBNode(OOBData(url: source.url))); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (details.chatState != null) { |  | ||||||
|       stanza.addChild( |  | ||||||
|         // TODO(Unknown): Move this into xep_0085.dart |  | ||||||
|         XMLNode.xmlns( |  | ||||||
|           tag: chatStateToString(details.chatState!), |  | ||||||
|           xmlns: chatStateXmlns, |  | ||||||
|         ), |  | ||||||
|       ); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     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: <String, String>{ |  | ||||||
|             'id': details.funReplacement!, |  | ||||||
|           }, |  | ||||||
|         ), |  | ||||||
|       ); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (details.messageRetraction != null) { |  | ||||||
|       stanza.addChild( |  | ||||||
|         XMLNode.xmlns( |  | ||||||
|           tag: 'apply-to', |  | ||||||
|           xmlns: fasteningXmlns, |  | ||||||
|           attributes: <String, String>{ |  | ||||||
|             '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( |  | ||||||
|         makeLastMessageCorrectionEdit( |  | ||||||
|           details.lastMessageCorrectionId!, |  | ||||||
|         ), |  | ||||||
|       ); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     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!, |  | ||||||
|           }, |  | ||||||
|         ), |  | ||||||
|       ); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     getAttributes().sendStanza( |  | ||||||
|       StanzaDetails( |       StanzaDetails( | ||||||
|         stanza, |         Stanza.message( | ||||||
|  |           to: to.toString(), | ||||||
|  |           id: extensions.get<MessageIdData>()?.id, | ||||||
|  |           type: extensions.get<ConversationTypeData>()?.conversationType == | ||||||
|  |                   ConversationType.groupchat | ||||||
|  |               ? 'groupchat' | ||||||
|  |               : 'chat', | ||||||
|  |           children: _messageSendingCallbacks | ||||||
|  |               .map((c) => c(extensions)) | ||||||
|  |               .flattened | ||||||
|  |               .toList(), | ||||||
|  |         ), | ||||||
|         awaitable: false, |         awaitable: false, | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   List<XMLNode> _messageSendingCallback( | ||||||
|  |     TypedMap<StanzaHandlerExtension> extensions, | ||||||
|  |   ) { | ||||||
|  |     if (extensions.get<ReplyData>() != null) { | ||||||
|  |       return []; | ||||||
|  |     } | ||||||
|  |     if (extensions.get<StickersData>() != null) { | ||||||
|  |       return []; | ||||||
|  |     } | ||||||
|  |     if (extensions.get<StatelessFileSharingData>() != null) { | ||||||
|  |       return []; | ||||||
|  |     } | ||||||
|  |     if (extensions.get<OOBData>() != null) { | ||||||
|  |       return []; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     final data = extensions.get<MessageBodyData>(); | ||||||
|  |     return data != null ? [data.toXML()] : []; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> postRegisterCallback() async { | ||||||
|  |     await super.postRegisterCallback(); | ||||||
|  | 
 | ||||||
|  |     // Register the sending callback | ||||||
|  |     registerMessageSendingCallback(_messageSendingCallback); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,4 +2,6 @@ abstract class MUCError {} | |||||||
| 
 | 
 | ||||||
| class InvalidStanzaFormat extends MUCError {} | class InvalidStanzaFormat extends MUCError {} | ||||||
| 
 | 
 | ||||||
|  | class InvalidDiscoInfoResponse extends MUCError {} | ||||||
|  | 
 | ||||||
| class NoNicknameSpecified extends MUCError {} | class NoNicknameSpecified extends MUCError {} | ||||||
|  | |||||||
| @ -8,29 +8,15 @@ class RoomInformation { | |||||||
|     required this.name, |     required this.name, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   factory RoomInformation.fromStanza({ |   factory RoomInformation.fromDiscoInfo({ | ||||||
|     required JID roomJID, |     required DiscoInfo discoInfo, | ||||||
|     required XMLNode stanza, |   }) => | ||||||
|   }) { |       RoomInformation( | ||||||
|     final featureNodes = stanza.children[0].findTags('feature'); |         jid: discoInfo.jid!, | ||||||
|     final identityNodes = stanza.children[0].findTags('identity'); |         features: discoInfo.features, | ||||||
| 
 |         name: discoInfo.identities[0].name!, | ||||||
|     if (featureNodes.isNotEmpty && identityNodes.isNotEmpty) { |  | ||||||
|       final features = featureNodes |  | ||||||
|           .map((xmlNode) => xmlNode.attributes['var'].toString()) |  | ||||||
|           .toList(); |  | ||||||
|       final name = identityNodes[0].attributes['name'].toString(); |  | ||||||
| 
 |  | ||||||
|       return RoomInformation( |  | ||||||
|         jid: roomJID, |  | ||||||
|         features: features, |  | ||||||
|         name: name, |  | ||||||
|       ); |       ); | ||||||
|     } else { | 
 | ||||||
|       // ignore: only_throw_errors |  | ||||||
|       throw InvalidStanzaFormat(); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   final JID jid; |   final JID jid; | ||||||
|   final List<String> features; |   final List<String> features; | ||||||
|   final String name; |   final String name; | ||||||
|  | |||||||
| @ -2,42 +2,42 @@ import 'package:moxxmpp/moxxmpp.dart'; | |||||||
| import 'package:moxxmpp/src/xeps/xep_0045/errors.dart'; | import 'package:moxxmpp/src/xeps/xep_0045/errors.dart'; | ||||||
| import 'package:moxxmpp/src/xeps/xep_0045/types.dart'; | import 'package:moxxmpp/src/xeps/xep_0045/types.dart'; | ||||||
| 
 | 
 | ||||||
|  | enum ConversationType { chat, groupchat, groupchatprivate } | ||||||
|  | 
 | ||||||
|  | class ConversationTypeData extends StanzaHandlerExtension { | ||||||
|  |   ConversationTypeData(this.conversationType); | ||||||
|  |   final ConversationType conversationType; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class MUCManager extends XmppManagerBase { | class MUCManager extends XmppManagerBase { | ||||||
|   MUCManager() : super(mucManager); |   MUCManager() : super(mucManager); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Future<bool> isSupported() async => true; |   Future<bool> isSupported() async => true; | ||||||
| 
 | 
 | ||||||
|   Future<Result<RoomInformation, MUCError>> queryRoomInformation({ |   Future<Result<RoomInformation, MUCError>> queryRoomInformation( | ||||||
|     required JID roomJID, |     JID roomJID, | ||||||
|   }) async { |   ) async { | ||||||
|     final attrs = getAttributes(); |  | ||||||
|     try { |     try { | ||||||
|       final result = await attrs.sendStanza( |       final attrs = getAttributes(); | ||||||
|         StanzaDetails( |       final result = await attrs | ||||||
|           Stanza.iq( |           .getManagerById<DiscoManager>(discoManager) | ||||||
|             type: 'get', |           ?.discoInfoQuery(roomJID); | ||||||
|             to: roomJID.toString(), |       if (result!.isType<DiscoError>()) { | ||||||
|             children: [ |         return Result(InvalidStanzaFormat()); | ||||||
|               XMLNode.xmlns( |       } | ||||||
|                 tag: 'query', |       final roomInformation = RoomInformation.fromDiscoInfo( | ||||||
|                 xmlns: discoInfoXmlns, |         discoInfo: result.get(), | ||||||
|               ) |  | ||||||
|             ], |  | ||||||
|           ), |  | ||||||
|         ), |  | ||||||
|       ); |       ); | ||||||
|       final roomInformation = |  | ||||||
|           RoomInformation.fromStanza(roomJID: roomJID, stanza: result!); |  | ||||||
|       return Result(roomInformation); |       return Result(roomInformation); | ||||||
|     } catch (e) { |     } catch (e) { | ||||||
|       return Result(InvalidStanzaFormat()); |       return Result(InvalidDiscoInfoResponse); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Future<Result<bool, MUCError>> joinRoom({ |   Future<Result<bool, MUCError>> joinRoom( | ||||||
|     required JID roomJIDWithNickname, |     JID roomJIDWithNickname, | ||||||
|   }) async { |   ) async { | ||||||
|     if (roomJIDWithNickname.resource.isEmpty) { |     if (roomJIDWithNickname.resource.isEmpty) { | ||||||
|       return Result(NoNicknameSpecified()); |       return Result(NoNicknameSpecified()); | ||||||
|     } |     } | ||||||
| @ -62,9 +62,9 @@ class MUCManager extends XmppManagerBase { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Future<Result<bool, MUCError>> leaveRoom({ |   Future<Result<bool, MUCError>> leaveRoom( | ||||||
|     required JID roomJIDWithNickname, |     JID roomJIDWithNickname, | ||||||
|   }) async { |   ) async { | ||||||
|     if (roomJIDWithNickname.resource.isEmpty) { |     if (roomJIDWithNickname.resource.isEmpty) { | ||||||
|       return Result(NoNicknameSpecified()); |       return Result(NoNicknameSpecified()); | ||||||
|     } |     } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Ikjot Singh Dhody
						Ikjot Singh Dhody