From 9e0f38154e031b73b0c1ace652be5cc9db7eaac0 Mon Sep 17 00:00:00 2001 From: "Alexander \"PapaTutuWawa" Date: Fri, 2 Jun 2023 22:00:44 +0200 Subject: [PATCH] feat(all): Various changes - Fix unavailable presence being sent *after* connecting - Migrate more APIs to the JID class - Advertise +notify for user avatar metadata --- packages/moxxmpp/lib/src/connection.dart | 22 +++-- packages/moxxmpp/lib/src/events.dart | 37 ++++++-- packages/moxxmpp/lib/src/managers/data.dart | 3 + .../lib/src/managers/data.freezed.dart | 46 ++++++++-- packages/moxxmpp/lib/src/presence.dart | 70 ++++++++------- packages/moxxmpp/lib/src/roster/roster.dart | 12 ++- packages/moxxmpp/lib/src/stanza.dart | 12 +++ packages/moxxmpp/lib/src/xeps/xep_0054.dart | 6 +- .../lib/src/xeps/xep_0060/xep_0060.dart | 12 +-- packages/moxxmpp/lib/src/xeps/xep_0084.dart | 86 +++++++++++++------ .../lib/src/xeps/xep_0198/xep_0198.dart | 10 ++- .../lib/src/xeps/xep_0384/xep_0384.dart | 7 +- 12 files changed, 217 insertions(+), 106 deletions(-) diff --git a/packages/moxxmpp/lib/src/connection.dart b/packages/moxxmpp/lib/src/connection.dart index 872a985..b752114 100644 --- a/packages/moxxmpp/lib/src/connection.dart +++ b/packages/moxxmpp/lib/src/connection.dart @@ -405,8 +405,7 @@ class XmppConnection { /// Returns true if we can send data through the socket. Future _canSendData() async { - return [XmppConnectionState.connected, XmppConnectionState.connecting] - .contains(await getConnectionState()); + return await getConnectionState() == XmppConnectionState.connected; } /// Sends a stanza described by [details] to the server. Until sent, the stanza is @@ -424,13 +423,17 @@ class XmppConnection { ); final completer = details.awaitable ? Completer() : null; - await _stanzaQueue.enqueueStanza( - StanzaQueueEntry( - details, - completer, - ), + final entry = StanzaQueueEntry( + details, + completer, ); + if (details.bypassQueue) { + await _sendStanzaImpl(entry); + } else { + await _stanzaQueue.enqueueStanza(entry); + } + return completer?.future; } @@ -523,7 +526,7 @@ class XmppConnection { if (await _canSendData()) { _socket.write(data.stanza.toXml()); } else { - _log.fine('Not sending dat as _canSendData() returned false.'); + _log.fine('Not sending data as _canSendData() returned false.'); } // Run post-send handlers @@ -535,6 +538,7 @@ class XmppConnection { false, null, newStanza, + excludeFromStreamManagement: details.excludeFromStreamManagement, ), ); _log.fine('Done'); @@ -835,7 +839,7 @@ class XmppConnection { await _reconnectionPolicy.setShouldReconnect(false); if (triggeredByUser) { - getPresenceManager()?.sendUnavailablePresence(); + await getPresenceManager()?.sendUnavailablePresence(); } _socket.prepareDisconnect(); diff --git a/packages/moxxmpp/lib/src/events.dart b/packages/moxxmpp/lib/src/events.dart index 2eaec7b..7b5eed1 100644 --- a/packages/moxxmpp/lib/src/events.dart +++ b/packages/moxxmpp/lib/src/events.dart @@ -7,6 +7,7 @@ import 'package:moxxmpp/src/stanza.dart'; import 'package:moxxmpp/src/xeps/xep_0030/types.dart'; import 'package:moxxmpp/src/xeps/xep_0060/xep_0060.dart'; import 'package:moxxmpp/src/xeps/xep_0066.dart'; +import 'package:moxxmpp/src/xeps/xep_0084.dart'; import 'package:moxxmpp/src/xeps/xep_0085.dart'; import 'package:moxxmpp/src/xeps/xep_0334.dart'; import 'package:moxxmpp/src/xeps/xep_0359.dart'; @@ -192,15 +193,35 @@ class SubscriptionRequestReceivedEvent extends XmppEvent { final JID from; } -/// Triggered when we receive a new or updated avatar -class AvatarUpdatedEvent extends XmppEvent { - AvatarUpdatedEvent({ - required this.jid, - required this.base64, - required this.hash, - }); - final String jid; +/// Triggered when we receive a new or updated avatar via XEP-0084 +class UserAvatarUpdatedEvent extends XmppEvent { + UserAvatarUpdatedEvent( + this.jid, + this.metadata, + ); + + /// The JID of the user updating their avatar. + final JID jid; + + /// The metadata of the avatar. + final List metadata; +} + +/// Triggered when we receive a new or updated avatar via XEP-0054 +class VCardAvatarUpdatedEvent extends XmppEvent { + VCardAvatarUpdatedEvent( + this.jid, + this.base64, + this.hash, + ); + + /// The JID of the entity that updated their avatar. + final JID jid; + + /// The base64-encoded avatar data. final String base64; + + /// The SHA-1 hash of the avatar. final String hash; } diff --git a/packages/moxxmpp/lib/src/managers/data.dart b/packages/moxxmpp/lib/src/managers/data.dart index cbc2f85..5245808 100644 --- a/packages/moxxmpp/lib/src/managers/data.dart +++ b/packages/moxxmpp/lib/src/managers/data.dart @@ -75,5 +75,8 @@ class StanzaHandlerData with _$StanzaHandlerData { MessageReactions? messageReactions, // The Id of the sticker pack this sticker belongs to String? stickerPackId, + // Flag indicating whether the stanza should be excluded from stream management's + // resending behaviour + @Default(false) bool excludeFromStreamManagement, }) = _StanzaHandlerData; } diff --git a/packages/moxxmpp/lib/src/managers/data.freezed.dart b/packages/moxxmpp/lib/src/managers/data.freezed.dart index cca8e46..f9164e0 100644 --- a/packages/moxxmpp/lib/src/managers/data.freezed.dart +++ b/packages/moxxmpp/lib/src/managers/data.freezed.dart @@ -71,7 +71,10 @@ mixin _$StanzaHandlerData { throw _privateConstructorUsedError; // Reactions data MessageReactions? get messageReactions => throw _privateConstructorUsedError; // The Id of the sticker pack this sticker belongs to - String? get stickerPackId => throw _privateConstructorUsedError; + String? get stickerPackId => + throw _privateConstructorUsedError; // Flag indicating whether the stanza should be excluded from stream management's +// resending behaviour + bool get excludeFromStreamManagement => throw _privateConstructorUsedError; @JsonKey(ignore: true) $StanzaHandlerDataCopyWith get copyWith => @@ -111,7 +114,8 @@ abstract class $StanzaHandlerDataCopyWith<$Res> { MessageRetractionData? messageRetraction, String? lastMessageCorrectionSid, MessageReactions? messageReactions, - String? stickerPackId}); + String? stickerPackId, + bool excludeFromStreamManagement}); } /// @nodoc @@ -154,6 +158,7 @@ class _$StanzaHandlerDataCopyWithImpl<$Res, $Val extends StanzaHandlerData> Object? lastMessageCorrectionSid = freezed, Object? messageReactions = freezed, Object? stickerPackId = freezed, + Object? excludeFromStreamManagement = null, }) { return _then(_value.copyWith( done: null == done @@ -264,6 +269,10 @@ class _$StanzaHandlerDataCopyWithImpl<$Res, $Val extends StanzaHandlerData> ? _value.stickerPackId : stickerPackId // ignore: cast_nullable_to_non_nullable as String?, + excludeFromStreamManagement: null == excludeFromStreamManagement + ? _value.excludeFromStreamManagement + : excludeFromStreamManagement // ignore: cast_nullable_to_non_nullable + as bool, ) as $Val); } } @@ -303,7 +312,8 @@ abstract class _$$_StanzaHandlerDataCopyWith<$Res> MessageRetractionData? messageRetraction, String? lastMessageCorrectionSid, MessageReactions? messageReactions, - String? stickerPackId}); + String? stickerPackId, + bool excludeFromStreamManagement}); } /// @nodoc @@ -344,6 +354,7 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res> Object? lastMessageCorrectionSid = freezed, Object? messageReactions = freezed, Object? stickerPackId = freezed, + Object? excludeFromStreamManagement = null, }) { return _then(_$_StanzaHandlerData( null == done @@ -454,6 +465,10 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res> ? _value.stickerPackId : stickerPackId // ignore: cast_nullable_to_non_nullable as String?, + excludeFromStreamManagement: null == excludeFromStreamManagement + ? _value.excludeFromStreamManagement + : excludeFromStreamManagement // ignore: cast_nullable_to_non_nullable + as bool, )); } } @@ -484,7 +499,8 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { this.messageRetraction, this.lastMessageCorrectionSid, this.messageReactions, - this.stickerPackId}) + this.stickerPackId, + this.excludeFromStreamManagement = false}) : _stanzaIds = stanzaIds, _other = other; @@ -595,10 +611,15 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { // The Id of the sticker pack this sticker belongs to @override final String? stickerPackId; +// Flag indicating whether the stanza should be excluded from stream management's +// resending behaviour + @override + @JsonKey() + final bool excludeFromStreamManagement; @override String toString() { - return 'StanzaHandlerData(done: $done, cancel: $cancel, cancelReason: $cancelReason, stanza: $stanza, retransmitted: $retransmitted, sims: $sims, sfs: $sfs, oob: $oob, originId: $originId, stanzaIds: $stanzaIds, reply: $reply, chatState: $chatState, isCarbon: $isCarbon, deliveryReceiptRequested: $deliveryReceiptRequested, isMarkable: $isMarkable, fun: $fun, funReplacement: $funReplacement, funCancellation: $funCancellation, encrypted: $encrypted, forceEncryption: $forceEncryption, encryptionType: $encryptionType, delayedDelivery: $delayedDelivery, other: $other, messageRetraction: $messageRetraction, lastMessageCorrectionSid: $lastMessageCorrectionSid, messageReactions: $messageReactions, stickerPackId: $stickerPackId)'; + return 'StanzaHandlerData(done: $done, cancel: $cancel, cancelReason: $cancelReason, stanza: $stanza, retransmitted: $retransmitted, sims: $sims, sfs: $sfs, oob: $oob, originId: $originId, stanzaIds: $stanzaIds, reply: $reply, chatState: $chatState, isCarbon: $isCarbon, deliveryReceiptRequested: $deliveryReceiptRequested, isMarkable: $isMarkable, fun: $fun, funReplacement: $funReplacement, funCancellation: $funCancellation, encrypted: $encrypted, forceEncryption: $forceEncryption, encryptionType: $encryptionType, delayedDelivery: $delayedDelivery, other: $other, messageRetraction: $messageRetraction, lastMessageCorrectionSid: $lastMessageCorrectionSid, messageReactions: $messageReactions, stickerPackId: $stickerPackId, excludeFromStreamManagement: $excludeFromStreamManagement)'; } @override @@ -652,7 +673,11 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { (identical(other.messageReactions, messageReactions) || other.messageReactions == messageReactions) && (identical(other.stickerPackId, stickerPackId) || - other.stickerPackId == stickerPackId)); + other.stickerPackId == stickerPackId) && + (identical(other.excludeFromStreamManagement, + excludeFromStreamManagement) || + other.excludeFromStreamManagement == + excludeFromStreamManagement)); } @override @@ -684,7 +709,8 @@ class _$_StanzaHandlerData implements _StanzaHandlerData { messageRetraction, lastMessageCorrectionSid, messageReactions, - stickerPackId + stickerPackId, + excludeFromStreamManagement ]); @JsonKey(ignore: true) @@ -720,7 +746,8 @@ abstract class _StanzaHandlerData implements StanzaHandlerData { final MessageRetractionData? messageRetraction, final String? lastMessageCorrectionSid, final MessageReactions? messageReactions, - final String? stickerPackId}) = _$_StanzaHandlerData; + final String? stickerPackId, + final bool excludeFromStreamManagement}) = _$_StanzaHandlerData; @override // Indicates to the runner that processing is now done. This means that all // pre-processing is done and no other handlers should be consulted. @@ -786,6 +813,9 @@ abstract class _StanzaHandlerData implements StanzaHandlerData { MessageReactions? get messageReactions; @override // The Id of the sticker pack this sticker belongs to String? get stickerPackId; + @override // Flag indicating whether the stanza should be excluded from stream management's +// resending behaviour + bool get excludeFromStreamManagement; @override @JsonKey(ignore: true) _$$_StanzaHandlerDataCopyWith<_$_StanzaHandlerData> get copyWith => diff --git a/packages/moxxmpp/lib/src/presence.dart b/packages/moxxmpp/lib/src/presence.dart index 2abf680..c9931ad 100644 --- a/packages/moxxmpp/lib/src/presence.dart +++ b/packages/moxxmpp/lib/src/presence.dart @@ -112,24 +112,48 @@ class PresenceManager extends XmppManagerBase { } /// Send an unavailable presence with no 'to' attribute. - void sendUnavailablePresence() { - getAttributes().sendStanza( + Future sendUnavailablePresence() async { + // Bypass the queue so that this get's sent immediately. + // If we do it like this, we can also block the disconnection + // until we're actually ready. + await getAttributes().sendStanza( StanzaDetails( Stanza.presence( type: 'unavailable', ), awaitable: false, + bypassQueue: true, + excludeFromStreamManagement: true, + ), + ); + } + + /// Sends a subscription request to [to]. + // TODO(PapaTutuWawa): Check if we're allowed to pre-approve + Future requestSubscription(JID to, {bool preApprove = false}) async { + await getAttributes().sendStanza( + StanzaDetails( + Stanza.presence( + type: preApprove ? 'subscribed' : 'subscribe', + to: to.toString(), + ), + awaitable: false, ), ); } - /// Sends a subscription request to [to]. - void sendSubscriptionRequest(String to) { - getAttributes().sendStanza( + /// Accept a subscription request from [to]. + Future acceptSubscriptionRequest(JID to) async { + await requestSubscription(to, preApprove: true); + } + + /// Send a subscription request rejection to [to]. + Future rejectSubscriptionRequest(JID to) async { + await getAttributes().sendStanza( StanzaDetails( Stanza.presence( - type: 'subscribe', - to: to, + type: 'unsubscribed', + to: to.toString(), ), awaitable: false, ), @@ -137,38 +161,12 @@ class PresenceManager extends XmppManagerBase { } /// Sends an unsubscription request to [to]. - void sendUnsubscriptionRequest(String to) { - getAttributes().sendStanza( + Future unsubscribe(JID to) async { + await getAttributes().sendStanza( StanzaDetails( Stanza.presence( type: 'unsubscribe', - to: to, - ), - awaitable: false, - ), - ); - } - - /// Accept a presence subscription request for [to]. - void sendSubscriptionRequestApproval(String to) { - getAttributes().sendStanza( - StanzaDetails( - Stanza.presence( - type: 'subscribed', - to: to, - ), - awaitable: false, - ), - ); - } - - /// Reject a presence subscription request for [to]. - void sendSubscriptionRequestRejection(String to) { - getAttributes().sendStanza( - StanzaDetails( - Stanza.presence( - type: 'unsubscribed', - to: to, + to: to.toString(), ), awaitable: false, ), diff --git a/packages/moxxmpp/lib/src/roster/roster.dart b/packages/moxxmpp/lib/src/roster/roster.dart index 93ae392..6c08d34 100644 --- a/packages/moxxmpp/lib/src/roster/roster.dart +++ b/packages/moxxmpp/lib/src/roster/roster.dart @@ -223,15 +223,21 @@ class RosterManager extends XmppManagerBase { return Result(result); } - /// Requests the roster following RFC 6121. - Future> requestRoster() async { + /// Requests the roster following RFC 6121. If [useRosterVersion] is set to false, then + /// roster versioning will not be used, even if the server supports it and we have a last + /// known roster version. + Future> requestRoster({ + bool useRosterVersion = true, + }) async { final attrs = getAttributes(); final query = XMLNode.xmlns( tag: 'query', xmlns: rosterXmlns, ); final rosterVersion = await _stateManager.getRosterVersion(); - if (rosterVersion != null && rosterVersioningAvailable()) { + if (rosterVersion != null && + rosterVersioningAvailable() && + useRosterVersion) { query.attributes['ver'] = rosterVersion; } diff --git a/packages/moxxmpp/lib/src/stanza.dart b/packages/moxxmpp/lib/src/stanza.dart index b06267a..0b07f8d 100644 --- a/packages/moxxmpp/lib/src/stanza.dart +++ b/packages/moxxmpp/lib/src/stanza.dart @@ -9,6 +9,8 @@ class StanzaDetails { this.awaitable = true, this.encrypted = false, this.forceEncryption = false, + this.bypassQueue = false, + this.excludeFromStreamManagement = false, }); /// The stanza to send. @@ -23,6 +25,16 @@ class StanzaDetails { final bool encrypted; final bool forceEncryption; + + /// Bypasses being put into the queue. Useful for sending stanzas that must go out + /// now, where it's okay if it does not get sent. + /// This should never have to be set to true. + final bool bypassQueue; + + /// This makes the Stream Management implementation, when available, ignore the stanza, + /// meaning that it gets counted but excluded from resending. + /// This should never have to be set to true. + final bool excludeFromStreamManagement; } /// A simple description of the element that may be inside a stanza diff --git a/packages/moxxmpp/lib/src/xeps/xep_0054.dart b/packages/moxxmpp/lib/src/xeps/xep_0054.dart index 0245044..48031ed 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0054.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0054.dart @@ -66,11 +66,7 @@ class VCardManager extends XmppManagerBase { final binval = vcardResult.get().photo?.binval; if (binval != null) { getAttributes().sendEvent( - AvatarUpdatedEvent( - jid: from, - base64: binval, - hash: hash, - ), + VCardAvatarUpdatedEvent(JID.fromString(from), binval, hash), ); } else { logger.warning('No avatar data found'); diff --git a/packages/moxxmpp/lib/src/xeps/xep_0060/xep_0060.dart b/packages/moxxmpp/lib/src/xeps/xep_0060/xep_0060.dart index bc3a32c..99f7a49 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0060/xep_0060.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0060/xep_0060.dart @@ -179,13 +179,13 @@ class PubSubManager extends XmppManagerBase { return options; } - Future> subscribe(String jid, String node) async { + Future> subscribe(JID jid, String node) async { final attrs = getAttributes(); final result = (await attrs.sendStanza( StanzaDetails( Stanza.iq( type: 'set', - to: jid, + to: jid.toString(), children: [ XMLNode.xmlns( tag: 'pubsub', @@ -222,13 +222,13 @@ class PubSubManager extends XmppManagerBase { return Result(subscription.attributes['subscription'] == 'subscribed'); } - Future> unsubscribe(String jid, String node) async { + Future> unsubscribe(JID jid, String node) async { final attrs = getAttributes(); final result = (await attrs.sendStanza( StanzaDetails( Stanza.iq( type: 'set', - to: jid, + to: jid.toString(), children: [ XMLNode.xmlns( tag: 'pubsub', @@ -398,14 +398,14 @@ class PubSubManager extends XmppManagerBase { } Future>> getItems( - String jid, + JID jid, String node, ) async { final result = (await getAttributes().sendStanza( StanzaDetails( Stanza.iq( type: 'get', - to: jid, + to: jid.toString(), children: [ XMLNode.xmlns( tag: 'pubsub', diff --git a/packages/moxxmpp/lib/src/xeps/xep_0084.dart b/packages/moxxmpp/lib/src/xeps/xep_0084.dart index 491a1b5..e676f44 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0084.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0084.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'package:moxxmpp/src/events.dart'; import 'package:moxxmpp/src/jid.dart'; import 'package:moxxmpp/src/managers/base.dart'; @@ -15,10 +16,17 @@ abstract class AvatarError {} class UnknownAvatarError extends AvatarError {} -class UserAvatar { - const UserAvatar({required this.base64, required this.hash}); +class UserAvatarData { + const UserAvatarData(this.base64, this.hash); + + /// The base64-encoded avatar data. final String base64; + + /// The SHA-1 hash of the raw avatar data. final String hash; + + /// The raw avatar data. + List get data => base64Decode(base64); } class UserAvatarMetadata { @@ -27,21 +35,44 @@ class UserAvatarMetadata { this.length, this.width, this.height, - this.mime, + this.type, + this.url, ); - /// The amount of bytes in the file + factory UserAvatarMetadata.fromXML(XMLNode node) { + assert( + node.tag == 'metadata' && + node.attributes['xmlns'] == userAvatarMetadataXmlns, + ' element required', + ); + + final width = node.attributes['width'] as String?; + final height = node.attributes['height'] as String?; + return UserAvatarMetadata( + node.attributes['id']! as String, + int.parse(node.attributes['bytes']! as String), + width != null ? int.parse(width) : null, + height != null ? int.parse(height) : null, + node.attributes['type']! as String, + node.attributes['url'] as String?, + ); + } + + /// The amount of bytes in the file. final int length; - /// The identifier of the avatar + /// The identifier of the avatar. final String id; - /// Image proportions - final int width; - final int height; + /// Image proportions. + final int? width; + final int? height; - /// The MIME type of the avatar - final String mime; + /// The URL where the avatar can be found. + final String? url; + + /// The MIME type of the avatar. + final String type; } /// NOTE: This class requires a PubSubManager @@ -51,13 +82,18 @@ class UserAvatarManager extends XmppManagerBase { PubSubManager _getPubSubManager() => getAttributes().getManagerById(pubsubManager)! as PubSubManager; + @override + List getDiscoFeatures() => [ + '$userAvatarMetadataXmlns+notify', + ]; + @override Future onXmppEvent(XmppEvent event) async { if (event is PubSubNotificationEvent) { - if (event.item.node != userAvatarDataXmlns) return; + if (event.item.node != userAvatarMetadataXmlns) return; - if (event.item.payload.tag != 'data' || - event.item.payload.attributes['xmlns'] != userAvatarDataXmlns) { + if (event.item.payload.tag != 'metadata' || + event.item.payload.attributes['xmlns'] != userAvatarMetadataXmlns) { logger.warning( 'Received avatar update from ${event.from} but the payload is invalid. Ignoring...', ); @@ -65,10 +101,12 @@ class UserAvatarManager extends XmppManagerBase { } getAttributes().sendEvent( - AvatarUpdatedEvent( - jid: event.from, - base64: event.item.payload.innerText(), - hash: event.item.id, + UserAvatarUpdatedEvent( + JID.fromString(event.from), + event.item.payload + .findTags('metadata', xmlns: userAvatarMetadataXmlns) + .map(UserAvatarMetadata.fromXML) + .toList(), ), ); } @@ -80,7 +118,7 @@ class UserAvatarManager extends XmppManagerBase { /// Requests the avatar from [jid]. Returns the avatar data if the request was /// successful. Null otherwise - Future> getUserAvatar(String jid) async { + Future> getUserAvatar(JID jid) async { final pubsub = _getPubSubManager(); final resultsRaw = await pubsub.getItems(jid, userAvatarDataXmlns); if (resultsRaw.isType()) return Result(UnknownAvatarError()); @@ -90,9 +128,9 @@ class UserAvatarManager extends XmppManagerBase { final item = results[0]; return Result( - UserAvatar( - base64: item.payload.innerText(), - hash: item.id, + UserAvatarData( + item.payload.innerText(), + item.id, ), ); } @@ -146,7 +184,7 @@ class UserAvatarManager extends XmppManagerBase { 'bytes': metadata.length.toString(), 'height': metadata.height.toString(), 'width': metadata.width.toString(), - 'type': metadata.mime, + 'type': metadata.type, 'id': metadata.id, }, ), @@ -163,14 +201,14 @@ class UserAvatarManager extends XmppManagerBase { } /// Subscribe the data and metadata node of [jid]. - Future> subscribe(String jid) async { + Future> subscribe(JID jid) async { await _getPubSubManager().subscribe(jid, userAvatarMetadataXmlns); return const Result(true); } /// Unsubscribe the data and metadata node of [jid]. - Future> unsubscribe(String jid) async { + Future> unsubscribe(JID jid) async { await _getPubSubManager().subscribe(jid, userAvatarMetadataXmlns); return const Result(true); diff --git a/packages/moxxmpp/lib/src/xeps/xep_0198/xep_0198.dart b/packages/moxxmpp/lib/src/xeps/xep_0198/xep_0198.dart index fd3a741..9f35880 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0198/xep_0198.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0198/xep_0198.dart @@ -399,10 +399,12 @@ class StreamManagementManager extends XmppManagerBase { Stanza stanza, StanzaHandlerData state, ) async { - await _incrementC2S(); - _unackedStanzas[_state.c2s] = stanza; - if (isStreamManagementEnabled()) { + await _incrementC2S(); + + if (state.excludeFromStreamManagement) return state; + + _unackedStanzas[_state.c2s] = stanza; await _sendAckRequest(); } @@ -414,6 +416,8 @@ class StreamManagementManager extends XmppManagerBase { _unackedStanzas.clear(); for (final stanza in stanzas) { + logger + .finest('Resending ${stanza.tag} with id ${stanza.attributes["id"]}'); await getAttributes().sendStanza( StanzaDetails( stanza, diff --git a/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart b/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart index a7fdf54..63b7397 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0384/xep_0384.dart @@ -516,8 +516,7 @@ abstract class BaseOmemoManager extends XmppManagerBase { JID jid, ) async { final pm = getAttributes().getManagerById(pubsubManager)!; - final result = - await pm.getItems(jid.toBare().toString(), omemoDevicesXmlns); + final result = await pm.getItems(jid.toBare(), omemoDevicesXmlns); if (result.isType()) return Result(UnknownOmemoError()); return Result(result.get>().first.payload); } @@ -543,7 +542,7 @@ abstract class BaseOmemoManager extends XmppManagerBase { ) async { // TODO(Unknown): Should we query the device list first? final pm = getAttributes().getManagerById(pubsubManager)!; - final bundlesRaw = await pm.getItems(jid.toString(), omemoBundlesXmlns); + final bundlesRaw = await pm.getItems(jid, omemoBundlesXmlns); if (bundlesRaw.isType()) return Result(UnknownOmemoError()); final bundles = bundlesRaw @@ -639,7 +638,7 @@ abstract class BaseOmemoManager extends XmppManagerBase { /// Subscribes to the device list PubSub node of [jid]. Future subscribeToDeviceListImpl(String jid) async { final pm = getAttributes().getManagerById(pubsubManager)!; - await pm.subscribe(jid, omemoDevicesXmlns); + await pm.subscribe(JID.fromString(jid), omemoDevicesXmlns); } /// Attempts to find out if [jid] supports omemo:2.