feat(xep,core): Migrate to moxlib's Result type

This commit is contained in:
PapaTutuWawa 2023-06-17 21:45:00 +02:00
parent c2f62e2967
commit 3cb5a568ce
34 changed files with 63 additions and 85 deletions

View File

@ -38,7 +38,6 @@ export 'package:moxxmpp/src/settings.dart';
export 'package:moxxmpp/src/socket.dart';
export 'package:moxxmpp/src/stanza.dart';
export 'package:moxxmpp/src/stringxml.dart';
export 'package:moxxmpp/src/types/result.dart';
export 'package:moxxmpp/src/util/typed_map.dart';
export 'package:moxxmpp/src/xeps/staging/extensible_file_thumbnails.dart';
export 'package:moxxmpp/src/xeps/staging/fast.dart';

View File

@ -25,7 +25,6 @@ import 'package:moxxmpp/src/settings.dart';
import 'package:moxxmpp/src/socket.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/util/queue.dart';
import 'package:moxxmpp/src/util/typed_map.dart';
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';

View File

@ -47,7 +47,6 @@ abstract class XmppManagerBase {
final result = await dm!.discoInfoQuery(
_managerAttributes.getConnectionSettings().jid.toDomain(),
shouldEncrypt: false,
);
if (result.isType<DiscoError>()) {
return false;

View File

@ -1,4 +1,4 @@
import 'package:moxlib/moxlib.dart';
import 'package:collection/collection.dart';
import 'package:moxxmpp/src/managers/data.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart';
@ -100,10 +100,10 @@ class StanzaHandler extends Handler {
matches &= firstTag?.xmlns == tagXmlns;
}
} else if (tagXmlns != null) {
matches &= listContains(
node.children,
matches &= node.children.firstWhereOrNull(
(XMLNode node_) => node_.attributes['xmlns'] == tagXmlns,
);
) !=
null;
}
return matches;

View File

@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/connection.dart';
@ -8,7 +9,6 @@ import 'package:moxxmpp/src/managers/base.dart';
import 'package:moxxmpp/src/settings.dart';
import 'package:moxxmpp/src/socket.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
/// The state a negotiator is currently in
enum NegotiatorState {
@ -117,8 +117,7 @@ abstract class XmppFeatureNegotiatorBase {
/// Returns true if a feature in [features], which are the children of the
/// <stream:features /> nonza, can be negotiated. Otherwise, returns false.
bool matchesFeature(List<XMLNode> features) {
return firstWhereOrNull(
features,
return features.firstWhereOrNull(
(XMLNode feature) => feature.attributes['xmlns'] == negotiatingXmlns,
) !=
null;

View File

@ -1,4 +1,5 @@
import 'dart:async';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/base.dart';
@ -10,7 +11,6 @@ import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
/// A function that will be called when presence, outside of subscription request
/// management, will be sent. Useful for managers that want to add [XMLNode]s to said

View File

@ -1,10 +1,10 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0198/xep_0198.dart';
import 'package:uuid/uuid.dart';

View File

@ -1,4 +1,4 @@
import 'package:moxlib/moxlib.dart';
import 'package:collection/collection.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
@ -13,15 +13,13 @@ abstract class SaslNegotiator extends XmppFeatureNegotiatorBase {
@override
bool matchesFeature(List<XMLNode> features) {
// Is SASL advertised?
final mechanisms = firstWhereOrNull(
features,
final mechanisms = features.firstWhereOrNull(
(XMLNode feature) => feature.attributes['xmlns'] == saslXmlns,
);
if (mechanisms == null) return false;
// Is SASL PLAIN advertised?
return firstWhereOrNull(
mechanisms.children,
return mechanisms.children.firstWhereOrNull(
(XMLNode mechanism) => mechanism.text == mechanismName,
) !=
null;

View File

@ -1,12 +1,12 @@
import 'dart:convert';
import 'package:logging/logging.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/rfcs/rfc_6120/sasl/errors.dart';
import 'package:moxxmpp/src/rfcs/rfc_6120/sasl/nonza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0388/negotiators.dart';
import 'package:moxxmpp/src/xeps/xep_0388/xep_0388.dart';
import 'package:saslprep/saslprep.dart';

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import 'dart:math' show Random;
import 'package:cryptography/cryptography.dart';
import 'package:logging/logging.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
@ -10,7 +11,6 @@ import 'package:moxxmpp/src/rfcs/rfc_6120/sasl/errors.dart';
import 'package:moxxmpp/src/rfcs/rfc_6120/sasl/kv.dart';
import 'package:moxxmpp/src/rfcs/rfc_6120/sasl/nonza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0388/negotiators.dart';
import 'package:moxxmpp/src/xeps/xep_0388/xep_0388.dart';
import 'package:random_string/random_string.dart';

View File

@ -1,9 +1,9 @@
import 'package:logging/logging.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
enum _StartTlsState { ready, requested }

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/attributes.dart';
import 'package:moxxmpp/src/managers/base.dart';
@ -14,7 +15,6 @@ import 'package:moxxmpp/src/roster/errors.dart';
import 'package:moxxmpp/src/roster/state.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
@immutable
class XmppRosterItem {

View File

@ -1,16 +0,0 @@
class Result<T, V> {
const Result(this._data)
: assert(
_data is T || _data is V,
'Invalid data type: Must be either $T or $V',
);
final dynamic _data;
bool isType<S>() => _data is S;
S get<S>() {
assert(_data is S, 'Data is not $S');
return _data as S;
}
}

View File

@ -33,7 +33,7 @@ class AsyncStanzaQueue {
this._canSendCallback,
);
/// The lock for accessing [AsyncStanzaQueue._lock] and [AsyncStanzaQueue._running].
/// The lock for accessing [AsyncStanzaQueue._queue].
final Lock _lock = Lock();
/// The actual job queue.
@ -44,9 +44,6 @@ class AsyncStanzaQueue {
final CanSendCallback _canSendCallback;
/// Indicates whether we are currently executing a job.
bool _running = false;
@visibleForTesting
Queue<StanzaQueueEntry> get queue => _queue;
@ -75,8 +72,6 @@ class AsyncStanzaQueue {
unawaited(
_runJob(_queue.removeFirst()),
);
} else {
_running = false;
}
});
}
@ -86,7 +81,6 @@ class AsyncStanzaQueue {
await _lock.synchronized(() {
if (_queue.isNotEmpty) {
_running = true;
unawaited(
_runJob(_queue.removeFirst()),
);

View File

@ -1,11 +1,11 @@
import 'package:collection/collection.dart';
import 'package:logging/logging.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0388/negotiators.dart';
import 'package:moxxmpp/src/xeps/xep_0388/xep_0388.dart';

View File

@ -1,4 +1,4 @@
import 'package:moxlib/moxlib.dart';
import 'package:collection/collection.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stringxml.dart';
@ -80,7 +80,7 @@ class DataForm {
final List<List<DataFormField>> items;
DataFormField? getFieldByVar(String varAttr) {
return firstWhereOrNull(fields, (field) => field.varAttr == varAttr);
return fields.firstWhereOrNull((field) => field.varAttr == varAttr);
}
XMLNode toXml() {

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:meta/meta.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';
@ -9,7 +10,6 @@ import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/util/wait.dart';
import 'package:moxxmpp/src/xeps/xep_0030/cache.dart';
import 'package:moxxmpp/src/xeps/xep_0030/errors.dart';

View File

@ -1,3 +1,4 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/base.dart';
@ -7,7 +8,6 @@ import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
abstract class VCardError {}

View File

@ -1,5 +1,6 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:meta/meta.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';
@ -9,7 +10,6 @@ import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0004.dart';
import 'package:moxxmpp/src/xeps/xep_0030/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0030/types.dart';

View File

@ -1,11 +1,11 @@
import 'dart:convert';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/base.dart';
import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0030/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0030/types.dart';
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
@ -225,7 +225,6 @@ class UserAvatarManager extends XmppManagerBase {
final response = await disco.discoItemsQuery(
jid,
node: userAvatarDataXmlns,
shouldEncrypt: false,
);
if (response.isType<DiscoError>()) return Result(UnknownAvatarError());

View File

@ -1,12 +1,12 @@
import 'package:collection/collection.dart';
import 'package:logging/logging.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0198/nonzas.dart';
import 'package:moxxmpp/src/xeps/xep_0198/state.dart';
import 'package:moxxmpp/src/xeps/xep_0198/xep_0198.dart';

View File

@ -1,10 +1,10 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/managers/base.dart';
import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0386.dart';
class CSIActiveNonza extends XMLNode {

View File

@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/events.dart';
@ -7,7 +8,6 @@ import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0030/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0030/types.dart';
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
@ -58,10 +58,10 @@ class HttpFileUploadManager extends XmppManagerBase {
/// Returns whether the entity provided an identity that tells us that we can ask it
/// for an HTTP upload slot.
bool _containsFileUploadIdentity(DiscoInfo info) {
return listContains(
info.identities,
return info.identities.firstWhereOrNull(
(Identity id) => id.category == 'store' && id.type == 'file',
);
) !=
null;
}
/// Extract the maximum filesize in octets from the disco response. Returns null

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'package:meta/meta.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';
@ -10,7 +11,6 @@ import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0030/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0030/types.dart';
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
@ -205,15 +205,18 @@ abstract class BaseOmemoManager extends XmppManagerBase {
) {
final keyElements = <String, List<XMLNode>>{};
for (final keys in result.encryptedKeys.entries) {
keyElements[keys.key] = keys.value.map((ek) => XMLNode(
keyElements[keys.key] = keys.value
.map(
(ek) => XMLNode(
tag: 'key',
attributes: {
'rid': ek.rid.toString(),
if (ek.kex)
'kex': 'true',
if (ek.kex) 'kex': 'true',
},
text: ek.value,
),).toList();
),
)
.toList();
}
final keysElements = keyElements.entries.map((entry) {
@ -235,7 +238,6 @@ abstract class BaseOmemoManager extends XmppManagerBase {
tag: 'payload',
text: base64Encode(result.ciphertext!),
),
XMLNode(
tag: 'header',
attributes: <String, String>{
@ -364,8 +366,8 @@ abstract class BaseOmemoManager extends XmppManagerBase {
..cancel = true
// If we have no device list for toJid, then the contact most likely does not
// support OMEMO:2
..cancelReason = result.deviceEncryptionErrors[toJid.toString()]!.first.error
is omemo.NoKeyMaterialAvailableError
..cancelReason = result.deviceEncryptionErrors[toJid.toString()]!.first
.error is omemo.NoKeyMaterialAvailableError
? OmemoNotSupportedForContactException()
: UnknownOmemoError()
// TODO
@ -578,7 +580,8 @@ abstract class BaseOmemoManager extends XmppManagerBase {
/// nodes.
///
/// On success, returns true. On failure, returns an OmemoError.
Future<Result<OmemoError, bool>> publishBundle(omemo.OmemoBundle bundle) async {
Future<Result<OmemoError, bool>> publishBundle(
omemo.OmemoBundle bundle,) async {
final attrs = getAttributes();
final pm = attrs.getManagerById<PubSubManager>(pubsubManager)!;
final bareJid = attrs.getFullJID().toBare();
@ -651,7 +654,7 @@ abstract class BaseOmemoManager extends XmppManagerBase {
/// On failure, returns an OmemoError.
Future<Result<OmemoError, bool>> supportsOmemo(JID jid) async {
final dm = getAttributes().getManagerById<DiscoManager>(discoManager)!;
final items = await dm.discoItemsQuery(jid.toBare(), shouldEncrypt: false);
final items = await dm.discoItemsQuery(jid.toBare());
if (items.isType<DiscoError>()) return Result(UnknownOmemoError());

View File

@ -1,10 +1,10 @@
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0388/negotiators.dart';
import 'package:moxxmpp/src/xeps/xep_0388/xep_0388.dart';

View File

@ -1,7 +1,7 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/rfcs/rfc_6120/sasl/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
/// A special type of [XmppFeatureNegotiatorBase] that is aware of SASL2.
abstract class Sasl2FeatureNegotiator extends XmppFeatureNegotiatorBase {

View File

@ -1,10 +1,10 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/rfcs/rfc_6120/sasl/errors.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/xeps/xep_0388/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0388/negotiators.dart';
import 'package:moxxmpp/src/xeps/xep_0388/user_agent.dart';

View File

@ -1,4 +1,4 @@
import 'package:moxlib/moxlib.dart';
import 'package:collection/collection.dart';
import 'package:moxxmpp/src/managers/base.dart';
import 'package:moxxmpp/src/managers/data.dart';
import 'package:moxxmpp/src/managers/handlers.dart';
@ -114,8 +114,7 @@ class StatelessFileSharingData implements StanzaHandlerExtension {
}
StatelessFileSharingUrlSource? getFirstUrlSource() {
return firstWhereOrNull(
sources,
return sources.firstWhereOrNull(
(StatelessFileSharingSource source) =>
source is StatelessFileSharingUrlSource,
) as StatelessFileSharingUrlSource?;

View File

@ -1,5 +1,5 @@
import 'dart:convert';
import 'package:moxlib/moxlib.dart';
import 'package:collection/collection.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/xeps/xep_0300.dart';
@ -54,8 +54,7 @@ class StatelessFileSharingEncryptedSource extends StatelessFileSharingSource {
final sources = element.firstTag('sources', xmlns: sfsXmlns)!.children;
// Find the first URL source
final source = firstWhereOrNull(
sources,
final source = sources.firstWhereOrNull(
(XMLNode child) =>
child.tag == 'url-data' && child.attributes['xmlns'] == urlDataXmlns,
)!;

View File

@ -1,4 +1,5 @@
import 'dart:convert';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/base.dart';
import 'package:moxxmpp/src/managers/data.dart';
@ -9,7 +10,6 @@ import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/rfcs/rfc_4790.dart';
import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/types/result.dart';
import 'package:moxxmpp/src/util/typed_map.dart';
import 'package:moxxmpp/src/xeps/xep_0060/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0060/xep_0060.dart';

View File

@ -1,6 +1,8 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:moxxmpp/src/parser.dart';
import 'package:test/test.dart';
import 'helpers/logging.dart';
const exampleXmlns1 = 'im:moxxmpp:example1';

View File

@ -1,3 +1,4 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:test/test.dart';

View File

@ -1,3 +1,4 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:test/test.dart';

View File

@ -1,6 +1,8 @@
import 'package:collection/collection.dart';
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:test/test.dart';
import '../helpers/logging.dart';
import '../helpers/xmpp.dart';