feat: Integrate the BaseRosterStateManager with the RosterManager
This commit is contained in:
parent
e2c8f79429
commit
995f2e0248
@ -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,
|
||||||
|
@ -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;
|
||||||
@ -87,18 +83,6 @@ 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() ?? '',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -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 {
|
||||||
@ -22,6 +23,12 @@ abstract class BaseRosterStateManager {
|
|||||||
|
|
||||||
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) {
|
||||||
final result = await loadRosterCache();
|
final result = await loadRosterCache();
|
||||||
|
Loading…
Reference in New Issue
Block a user