feat: Integrate the BaseRosterStateManager with the RosterManager

This commit is contained in:
PapaTutuWawa 2023-01-07 16:26:15 +01:00
parent e2c8f79429
commit 995f2e0248
3 changed files with 53 additions and 62 deletions

View File

@ -1,6 +1,7 @@
import 'package:moxxmpp/src/connection.dart'; import 'package:moxxmpp/src/connection.dart';
import 'package:moxxmpp/src/jid.dart'; import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/data.dart'; import 'package:moxxmpp/src/managers/data.dart';
import 'package:moxxmpp/src/roster/roster.dart';
import 'package:moxxmpp/src/stanza.dart'; import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/xeps/xep_0030/types.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_0060/xep_0060.dart';
@ -53,6 +54,14 @@ class StreamResumedEvent extends XmppEvent {
/// Triggered when stream resumption failed /// Triggered when stream resumption failed
class StreamResumeFailedEvent extends XmppEvent {} class StreamResumeFailedEvent extends XmppEvent {}
/// Triggered when a roster push is received
class RosterPushEvent extends XmppEvent {
RosterPushEvent({ required this.item, this.ver });
final XmppRosterItem item;
final String? ver;
}
/// Triggered when a message is received
class MessageEvent extends XmppEvent { class MessageEvent extends XmppEvent {
MessageEvent({ MessageEvent({
required this.body, required this.body,

View File

@ -1,3 +1,4 @@
import 'dart:async';
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';
@ -8,6 +9,7 @@ import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart'; import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart'; import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/roster/errors.dart'; import 'package:moxxmpp/src/roster/errors.dart';
import 'package:moxxmpp/src/roster/state.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/types/result.dart'; import 'package:moxxmpp/src/types/result.dart';
@ -33,12 +35,6 @@ class RosterRequestResult {
String? ver; String? ver;
} }
class RosterPushEvent extends XmppEvent {
RosterPushEvent({ required this.item, this.ver });
final XmppRosterItem item;
final String? ver;
}
/// A Stub feature negotiator for finding out whether roster versioning is supported. /// A Stub feature negotiator for finding out whether roster versioning is supported.
class RosterFeatureNegotiator extends XmppFeatureNegotiatorBase { class RosterFeatureNegotiator extends XmppFeatureNegotiatorBase {
RosterFeatureNegotiator() : _supported = false, super(11, false, rosterVersioningXmlns, rosterNegotiator); RosterFeatureNegotiator() : _supported = false, super(11, false, rosterVersioningXmlns, rosterNegotiator);
@ -65,8 +61,8 @@ class RosterFeatureNegotiator extends XmppFeatureNegotiatorBase {
/// This manager requires a RosterFeatureNegotiator to be registered. /// This manager requires a RosterFeatureNegotiator to be registered.
class RosterManager extends XmppManagerBase { class RosterManager extends XmppManagerBase {
RosterManager() : _rosterVersion = null, super(); RosterManager(this._stateManager) : super();
String? _rosterVersion; final BaseRosterStateManager _stateManager;
@override @override
String getId() => rosterManager; String getId() => rosterManager;
@ -86,19 +82,7 @@ class RosterManager extends XmppManagerBase {
@override @override
Future<bool> isSupported() async => true; Future<bool> isSupported() async => true;
/// Commit the current roster to storage.
Future<void> commitLastRosterVersion(String version) async {}
/// Load the last roster data
Future<void> loadLastRosterVersion() async {}
void setRosterVersion(String ver) {
assert(_rosterVersion == null, 'A roster version must not be empty');
_rosterVersion = ver;
}
Future<StanzaHandlerData> _onRosterPush(Stanza stanza, StanzaHandlerData state) async { Future<StanzaHandlerData> _onRosterPush(Stanza stanza, StanzaHandlerData state) async {
final attrs = getAttributes(); final attrs = getAttributes();
final from = stanza.attributes['from'] as String?; final from = stanza.attributes['from'] as String?;
@ -122,21 +106,20 @@ class RosterManager extends XmppManagerBase {
return state.copyWith(done: true); return state.copyWith(done: true);
} }
if (query.attributes['ver'] != null) { unawaited(
final ver = query.attributes['ver']! as String; _stateManager.handleRosterPush(
await commitLastRosterVersion(ver); RosterPushEvent(
_rosterVersion = ver; item: XmppRosterItem(
} jid: item.attributes['jid']! as String,
subscription: item.attributes['subscription']! as String,
attrs.sendEvent(RosterPushEvent( ask: item.attributes['ask'] as String?,
item: XmppRosterItem( name: item.attributes['name'] as String?,
jid: item.attributes['jid']! as String, ),
subscription: item.attributes['subscription']! as String, ver: query.attributes['ver'] as String?,
ask: item.attributes['ask'] as String?, ),
name: item.attributes['name'] as String?,
), ),
ver: query.attributes['ver'] as String?, );
),);
await attrs.sendStanza(stanza.reply()); await attrs.sendStanza(stanza.reply());
return state.copyWith(done: true); return state.copyWith(done: true);
@ -146,38 +129,34 @@ class RosterManager extends XmppManagerBase {
/// the server deems a regular roster response more efficient than n roster pushes. /// the server deems a regular roster response more efficient than n roster pushes.
Future<Result<RosterRequestResult, RosterError>> _handleRosterResponse(XMLNode? query) async { Future<Result<RosterRequestResult, RosterError>> _handleRosterResponse(XMLNode? query) async {
final List<XmppRosterItem> items; final List<XmppRosterItem> items;
String? rosterVersion;
if (query != null) { if (query != null) {
items = query.children.map((item) => XmppRosterItem( items = query.children.map(
name: item.attributes['name'] as String?, (item) => XmppRosterItem(
jid: item.attributes['jid']! as String, name: item.attributes['name'] as String?,
subscription: item.attributes['subscription']! as String, jid: item.attributes['jid']! as String,
ask: item.attributes['ask'] as String?, subscription: item.attributes['subscription']! as String,
groups: item.findTags('group').map((groupNode) => groupNode.innerText()).toList(), ask: item.attributes['ask'] as String?,
),).toList(); groups: item.findTags('group').map((groupNode) => groupNode.innerText()).toList(),
),
).toList();
if (query.attributes['ver'] != null) { rosterVersion = query.attributes['ver'] as String?;
final ver_ = query.attributes['ver']! as String;
await commitLastRosterVersion(ver_);
_rosterVersion = ver_;
}
} else { } else {
logger.warning('Server response to roster request without roster versioning does not contain a <query /> element, while the type is not error. This violates RFC6121'); logger.warning('Server response to roster request without roster versioning does not contain a <query /> element, while the type is not error. This violates RFC6121');
return Result(NoQueryError()); return Result(NoQueryError());
} }
final ver = query.attributes['ver'] as String?; final result = RosterRequestResult(
if (ver != null) { items: items,
_rosterVersion = ver; ver: rosterVersion,
await commitLastRosterVersion(ver);
}
return Result(
RosterRequestResult(
items: items,
ver: ver,
),
); );
unawaited(
_stateManager.handleRosterFetch(result),
);
return Result(result);
} }
/// Requests the roster following RFC 6121 without using roster versioning. /// Requests the roster following RFC 6121 without using roster versioning.
@ -207,10 +186,6 @@ class RosterManager extends XmppManagerBase {
/// Requests a series of roster pushes according to RFC6121. Requires that the server /// Requests a series of roster pushes according to RFC6121. Requires that the server
/// advertises urn:xmpp:features:rosterver in the stream features. /// advertises urn:xmpp:features:rosterver in the stream features.
Future<Result<RosterRequestResult?, RosterError>> requestRosterPushes() async { Future<Result<RosterRequestResult?, RosterError>> requestRosterPushes() async {
if (_rosterVersion == null) {
await loadLastRosterVersion();
}
final attrs = getAttributes(); final attrs = getAttributes();
final result = await attrs.sendStanza( final result = await attrs.sendStanza(
Stanza.iq( Stanza.iq(
@ -220,7 +195,7 @@ class RosterManager extends XmppManagerBase {
tag: 'query', tag: 'query',
xmlns: rosterXmlns, xmlns: rosterXmlns,
attributes: { attributes: {
'ver': _rosterVersion ?? '' 'ver': await _stateManager.getRosterVersion() ?? '',
}, },
) )
], ],

View File

@ -1,4 +1,5 @@
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/roster/roster.dart'; import 'package:moxxmpp/src/roster/roster.dart';
class _RosterProcessTriple { class _RosterProcessTriple {
@ -21,6 +22,12 @@ abstract class BaseRosterStateManager {
Future<RosterCacheLoadResult> loadRosterCache(); Future<RosterCacheLoadResult> loadRosterCache();
Future<void> commitRoster(String? version, List<String> removed, List<XmppRosterItem> modified, List<XmppRosterItem> added); Future<void> commitRoster(String? version, List<String> removed, List<XmppRosterItem> modified, List<XmppRosterItem> added);
Future<String?> getRosterVersion() async {
await _loadRosterCache();
return currentVersion;
}
Future<void> _loadRosterCache() async { Future<void> _loadRosterCache() async {
if (currentRoster == null) { if (currentRoster == null) {