feat(all): Restrict extensions to StanzaHandlerExtension

This commit is contained in:
PapaTutuWawa 2023-06-06 21:19:42 +02:00
parent cf3287ccf4
commit 60279a84e0
25 changed files with 176 additions and 94 deletions

View File

@ -533,7 +533,7 @@ class XmppConnection {
// Run post-send handlers // Run post-send handlers
_log.fine('Running post stanza handlers..'); _log.fine('Running post stanza handlers..');
final extensions = TypedMap() final extensions = TypedMap<StanzaHandlerExtension>()
..set(StreamManagementData(details.excludeFromStreamManagement)); ..set(StreamManagementData(details.excludeFromStreamManagement));
await _runOutgoingPostStanzaHandlers( await _runOutgoingPostStanzaHandlers(
newStanza, newStanza,

View File

@ -8,6 +8,7 @@ import 'package:moxxmpp/src/util/typed_map.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';
import 'package:moxxmpp/src/xeps/xep_0084.dart'; import 'package:moxxmpp/src/xeps/xep_0084.dart';
import 'package:moxxmpp/src/xeps/xep_0333.dart';
abstract class XmppEvent {} abstract class XmppEvent {}
@ -90,7 +91,7 @@ class MessageEvent extends XmppEvent {
final StanzaError? error; final StanzaError? error;
/// Data added by other handlers. /// Data added by other handlers.
final TypedMap extensions; final TypedMap<StanzaHandlerExtension> extensions;
} }
/// Triggered when a client responds to our delivery receipt request /// Triggered when a client responds to our delivery receipt request
@ -101,13 +102,19 @@ class DeliveryReceiptReceivedEvent extends XmppEvent {
} }
class ChatMarkerEvent extends XmppEvent { class ChatMarkerEvent extends XmppEvent {
ChatMarkerEvent({ ChatMarkerEvent(
required this.type, this.from,
required this.from, this.type,
required this.id, this.id,
}); );
/// The entity that sent the chat marker.
final JID from; final JID from;
final String type;
/// The type of chat marker that was sent.
final ChatMarker type;
/// The id of the message that the marker applies to.
final String id; final String id;
} }

View File

@ -1,6 +1,8 @@
import 'package:moxxmpp/src/stanza.dart'; import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
abstract class StanzaHandlerExtension {}
class StanzaHandlerData { class StanzaHandlerData {
StanzaHandlerData( StanzaHandlerData(
this.done, this.done,
@ -41,5 +43,5 @@ class StanzaHandlerData {
bool forceEncryption; bool forceEncryption;
/// Additional data from other managers. /// Additional data from other managers.
final TypedMap extensions; final TypedMap<StanzaHandlerExtension> extensions;
} }

View File

@ -16,7 +16,7 @@ import 'package:moxxmpp/src/xeps/xep_0461.dart';
/// A callback that is called whenever a message is sent using /// A callback that is called whenever a message is sent using
/// [MessageManager.sendMessage]. The input the typed map that is passed to /// [MessageManager.sendMessage]. The input the typed map that is passed to
/// sendMessage. /// sendMessage.
typedef MessageSendingCallback = List<XMLNode> Function(TypedMap); typedef MessageSendingCallback = List<XMLNode> Function(TypedMap<StanzaHandlerExtension>);
/// The raw content of the <body /> element. /// The raw content of the <body /> element.
class MessageBodyData { class MessageBodyData {
@ -85,7 +85,7 @@ class MessageManager extends XmppManagerBase {
/// Send an unawaitable message to [to]. [extensions] is a typed map that contains /// Send an unawaitable message to [to]. [extensions] is a typed map that contains
/// data for building the message. /// data for building the message.
Future<void> sendMessage(JID to, TypedMap extensions) async { Future<void> sendMessage(JID to, TypedMap<StanzaHandlerExtension> extensions) async {
await getAttributes().sendStanza( await getAttributes().sendStanza(
StanzaDetails( StanzaDetails(
Stanza.message( Stanza.message(
@ -102,7 +102,7 @@ class MessageManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
if (extensions.get<ReplyData>() != null) { if (extensions.get<ReplyData>() != null) {
return []; return [];
} }

View File

@ -1,10 +1,10 @@
/// A map, similar to Map, but always uses the type of the value as the key. /// A map, similar to Map, but always uses the type of the value as the key.
class TypedMap { class TypedMap<B> {
/// The internal mapping of type -> data /// The internal mapping of type -> data
final Map<Object, Object> _data = {}; final Map<Object, B> _data = {};
/// Associate the type of [value] with [value] in the map. /// Associate the type of [value] with [value] in the map.
void set<T extends Object>(T value) { void set<T extends B>(T value) {
_data[T] = value; _data[T] = value;
} }

View File

@ -13,7 +13,7 @@ import 'package:moxxmpp/src/xeps/xep_0446.dart';
const fileUploadNotificationXmlns = 'proto:urn:xmpp:fun:0'; const fileUploadNotificationXmlns = 'proto:urn:xmpp:fun:0';
/// Indicates a file upload notification. /// Indicates a file upload notification.
class FileUploadNotificationData { class FileUploadNotificationData implements StanzaHandlerExtension {
const FileUploadNotificationData(this.metadata); const FileUploadNotificationData(this.metadata);
/// The file metadata indicated in the upload notification. /// The file metadata indicated in the upload notification.
@ -31,7 +31,7 @@ class FileUploadNotificationData {
} }
/// Indicates that a file upload has been cancelled. /// Indicates that a file upload has been cancelled.
class FileUploadNotificationCancellationData { class FileUploadNotificationCancellationData implements StanzaHandlerExtension {
const FileUploadNotificationCancellationData(this.id); const FileUploadNotificationCancellationData(this.id);
/// The id of the upload notifiaction that is cancelled. /// The id of the upload notifiaction that is cancelled.
@ -49,7 +49,7 @@ class FileUploadNotificationCancellationData {
} }
/// Indicates that a file upload has been completed. /// Indicates that a file upload has been completed.
class FileUploadNotificationReplacementData { class FileUploadNotificationReplacementData implements StanzaHandlerExtension {
const FileUploadNotificationReplacementData(this.id); const FileUploadNotificationReplacementData(this.id);
/// The id of the upload notifiaction that is replaced. /// The id of the upload notifiaction that is replaced.
@ -141,7 +141,7 @@ class FileUploadNotificationManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final fun = extensions.get<FileUploadNotificationData>(); final fun = extensions.get<FileUploadNotificationData>();
if (fun != null) { if (fun != null) {
return [fun.toXML()]; return [fun.toXML()];

View File

@ -9,7 +9,7 @@ import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
/// A data class representing the jabber:x:oob tag. /// A data class representing the jabber:x:oob tag.
class OOBData { class OOBData implements StanzaHandlerExtension {
const OOBData(this.url, this.desc); const OOBData(this.url, this.desc);
/// The communicated URL of the OOB data /// The communicated URL of the OOB data
@ -68,7 +68,7 @@ class OOBManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<OOBData>(); final data = extensions.get<OOBData>();
return data != null return data != null
? [ ? [

View File

@ -8,14 +8,14 @@ import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
enum ChatState { enum ChatState implements StanzaHandlerExtension {
active, active,
composing, composing,
paused, paused,
inactive, inactive,
gone; gone;
factory ChatState.fromString(String state) { factory ChatState.fromName(String state) {
switch (state) { switch (state) {
case 'active': case 'active':
return ChatState.active; return ChatState.active;
@ -27,9 +27,9 @@ enum ChatState {
return ChatState.inactive; return ChatState.inactive;
case 'gone': case 'gone':
return ChatState.gone; return ChatState.gone;
default:
return ChatState.gone;
} }
throw Exception('Invalid chat state $state');
} }
@override @override
@ -81,7 +81,13 @@ class ChatStateManager extends XmppManagerBase {
StanzaHandlerData state, StanzaHandlerData state,
) async { ) async {
final element = state.stanza.firstTagByXmlns(chatStateXmlns)!; final element = state.stanza.firstTagByXmlns(chatStateXmlns)!;
state.extensions.set(ChatState.fromString(element.tag));
try {
state.extensions.set(ChatState.fromName(element.tag));
} catch (_) {
logger.finest('Ignoring invalid chat state ${element.tag}');
}
return state; return state;
} }
@ -106,7 +112,7 @@ class ChatStateManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<ChatState>(); final data = extensions.get<ChatState>();
return data != null return data != null
? [ ? [

View File

@ -10,7 +10,7 @@ import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
class MessageDeliveryReceiptData { class MessageDeliveryReceiptData implements StanzaHandlerExtension {
const MessageDeliveryReceiptData(this.receiptRequested); const MessageDeliveryReceiptData(this.receiptRequested);
/// Indicates whether a delivery receipt is requested or not. /// Indicates whether a delivery receipt is requested or not.
@ -28,7 +28,7 @@ class MessageDeliveryReceiptData {
} }
} }
class MessageDeliveryReceivedData { class MessageDeliveryReceivedData implements StanzaHandlerExtension {
const MessageDeliveryReceivedData(this.id); const MessageDeliveryReceivedData(this.id);
/// The stanza id of the message we received. /// The stanza id of the message we received.
@ -104,7 +104,7 @@ class MessageDeliveryReceiptManager extends XmppManagerBase {
return state..done = true; return state..done = true;
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<MessageDeliveryReceivedData>(); final data = extensions.get<MessageDeliveryReceivedData>();
return data != null return data != null
? [ ? [

View File

@ -1,4 +1,6 @@
class StreamManagementData { import 'package:moxxmpp/src/managers/data.dart';
class StreamManagementData implements StanzaHandlerExtension {
const StreamManagementData(this.exclude); const StreamManagementData(this.exclude);
/// Whether the stanza should be exluded from the StreamManagement's resend queue. /// Whether the stanza should be exluded from the StreamManagement's resend queue.

View File

@ -8,7 +8,7 @@ import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart'; import 'package:moxxmpp/src/stanza.dart';
@immutable @immutable
class DelayedDeliveryData { class DelayedDeliveryData implements StanzaHandlerExtension {
const DelayedDeliveryData(this.from, this.timestamp); const DelayedDeliveryData(this.from, this.timestamp);
/// The timestamp the message was originally sent. /// The timestamp the message was originally sent.

View File

@ -14,7 +14,7 @@ import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
import 'package:moxxmpp/src/xeps/xep_0297.dart'; import 'package:moxxmpp/src/xeps/xep_0297.dart';
import 'package:moxxmpp/src/xeps/xep_0386.dart'; import 'package:moxxmpp/src/xeps/xep_0386.dart';
class CarbonsData { class CarbonsData implements StanzaHandlerExtension {
const CarbonsData(this.isCarbon); const CarbonsData(this.isCarbon);
/// Indicates whether this message is a carbon. /// Indicates whether this message is a carbon.

View File

@ -8,7 +8,7 @@ import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
class LastMessageCorrectionData { class LastMessageCorrectionData implements StanzaHandlerExtension {
const LastMessageCorrectionData(this.id); const LastMessageCorrectionData(this.id);
/// The id the LMC applies to. /// The id the LMC applies to.
@ -57,7 +57,7 @@ class LastMessageCorrectionManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<LastMessageCorrectionData>(); final data = extensions.get<LastMessageCorrectionData>();
return data != null return data != null
? [ ? [

View File

@ -10,30 +10,77 @@ import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
class ChatMarkerData { enum ChatMarker {
const ChatMarkerData(this.isMarkable); received,
displayed,
acknowledged;
factory ChatMarker.fromName(String name) {
switch (name) {
case 'received': return ChatMarker.received;
case 'displayed': return ChatMarker.displayed;
case 'acknowledged': return ChatMarker.acknowledged;
}
throw Exception('Invalid chat marker $name');
}
XMLNode toXML() {
String tag;
switch (this) {
case ChatMarker.received:
tag = 'received';
break;
case ChatMarker.displayed:
tag = 'displayed';
break;
case ChatMarker.acknowledged:
tag = 'acknowledged';
break;
}
return XMLNode.xmlns(
tag: tag,
xmlns: chatMarkersXmlns,
);
}
}
class MarkableData implements StanzaHandlerExtension {
const MarkableData(this.isMarkable);
/// Indicates whether the message can be replied to with a chat marker. /// Indicates whether the message can be replied to with a chat marker.
final bool isMarkable; final bool isMarkable;
}
XMLNode makeChatMarkerMarkable() { XMLNode toXML() {
assert(isMarkable, '');
return XMLNode.xmlns( return XMLNode.xmlns(
tag: 'markable', tag: 'markable',
xmlns: chatMarkersXmlns, xmlns: chatMarkersXmlns,
); );
}
} }
XMLNode makeChatMarker(String tag, String id) { class ChatMarkerData implements StanzaHandlerExtension {
assert( const ChatMarkerData(this.marker, this.id);
['received', 'displayed', 'acknowledged'].contains(tag),
'Invalid chat marker', /// The actual chat state
); final ChatMarker marker;
/// The ID the chat marker applies to
final String id;
XMLNode toXML() {
final tag = marker.toXML();
return XMLNode.xmlns( return XMLNode.xmlns(
tag: tag, tag: tag.tag,
xmlns: chatMarkersXmlns, xmlns: chatMarkersXmlns,
attributes: {'id': id}, attributes: {
'id': id,
},
); );
}
} }
class ChatMarkerManager extends XmppManagerBase { class ChatMarkerManager extends XmppManagerBase {
@ -60,31 +107,41 @@ class ChatMarkerManager extends XmppManagerBase {
Stanza message, Stanza message,
StanzaHandlerData state, StanzaHandlerData state,
) async { ) async {
final marker = message.firstTagByXmlns(chatMarkersXmlns)!; final element = message.firstTagByXmlns(chatMarkersXmlns)!;
// Handle the <markable /> explicitly // Handle the <markable /> explicitly
if (marker.tag == 'markable') { if (element.tag == 'markable') {
return state..extensions.set(const ChatMarkerData(true)); return state..extensions.set(const MarkableData(true));
} }
if (!['received', 'displayed', 'acknowledged'].contains(marker.tag)) { try {
logger.warning("Unknown message marker '${marker.tag}' found.");
} else {
getAttributes().sendEvent( getAttributes().sendEvent(
ChatMarkerEvent( ChatMarkerEvent(
from: JID.fromString(message.from!), JID.fromString(message.from!),
type: marker.tag, ChatMarker.fromName(element.tag),
id: marker.attributes['id']! as String, element.attributes['id']! as String,
), ),
); );
} catch (_) {
logger.warning("Unknown message marker '${element.tag}' found.");
} }
return state..done = true; return state..done = true;
} }
// TODO: Implement List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
List<XMLNode> _messageSendingCallback(TypedMap extensions) { final children = List<XMLNode>.empty(growable: true);
return []; final marker = extensions.get<ChatMarkerData>();
if (marker != null) {
children.add(marker.toXML());
}
final markable = extensions.get<MarkableData>();
if (markable != null) {
children.add(markable.toXML());
}
return children;
} }
@override @override
@ -92,8 +149,6 @@ class ChatMarkerManager extends XmppManagerBase {
await super.postRegisterCallback(); await super.postRegisterCallback();
// Register the sending callback // Register the sending callback
getAttributes() getAttributes().getManagerById<MessageManager>(messageManager)?.registerMessageSendingCallback(_messageSendingCallback);
.getManagerById<MessageManager>(messageManager)
?.registerMessageSendingCallback(_messageSendingCallback);
} }
} }

View File

@ -54,6 +54,13 @@ enum MessageProcessingHint {
} }
} }
class MessageProcessingHintData implements StanzaHandlerExtension {
const MessageProcessingHintData(this.hints);
/// The attached message processing hints.
final List<MessageProcessingHint> hints;
}
class MessageProcessingHintManager extends XmppManagerBase { class MessageProcessingHintManager extends XmppManagerBase {
MessageProcessingHintManager() : super(messageProcessingHintManager); MessageProcessingHintManager() : super(messageProcessingHintManager);
@ -76,18 +83,19 @@ class MessageProcessingHintManager extends XmppManagerBase {
Stanza stanza, Stanza stanza,
StanzaHandlerData state, StanzaHandlerData state,
) async { ) async {
// TODO(Unknown): Do we need to consider multiple hints? final elements = stanza.findTagsByXmlns(messageProcessingHintsXmlns);
final element = stanza.findTagsByXmlns(messageProcessingHintsXmlns).first; return state
return state..extensions.set(MessageProcessingHint.fromName(element.tag)); ..extensions.set(
MessageProcessingHintData(
elements.map((element) => MessageProcessingHint.fromName(element.tag)).toList(),
),
);
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
// TODO(Unknown): Do we need to consider multiple hints? final data = extensions.get<MessageProcessingHintData>();
final data = extensions.get<MessageProcessingHint>();
return data != null return data != null
? [ ? data.hints.map((hint) => hint.toXML()).toList()
data.toXML(),
]
: []; : [];
} }

View File

@ -34,7 +34,7 @@ class StanzaId {
} }
} }
class StableIdData { class StableIdData implements StanzaHandlerExtension {
const StableIdData(this.originId, this.stanzaIds); const StableIdData(this.originId, this.stanzaIds);
/// <origin-id /> /// <origin-id />
@ -123,7 +123,7 @@ class StableIdManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<StableIdData>(); final data = extensions.get<StableIdData>();
return data != null ? data.toXML() : []; return data != null ? data.toXML() : [];
} }

View File

@ -6,7 +6,7 @@ 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';
enum ExplicitEncryptionType { enum ExplicitEncryptionType implements StanzaHandlerExtension {
otr, otr,
legacyOpenPGP, legacyOpenPGP,
openPGP, openPGP,

View File

@ -7,7 +7,7 @@ import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/xeps/staging/extensible_file_thumbnails.dart'; import 'package:moxxmpp/src/xeps/staging/extensible_file_thumbnails.dart';
class StatelessMediaSharingData { class StatelessMediaSharingData implements StanzaHandlerExtension {
const StatelessMediaSharingData({ const StatelessMediaSharingData({
required this.mediaType, required this.mediaType,
required this.size, required this.size,

View File

@ -8,7 +8,7 @@ import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
class MessageRetractionData { class MessageRetractionData implements StanzaHandlerExtension {
MessageRetractionData(this.id, this.fallback); MessageRetractionData(this.id, this.fallback);
/// A potential fallback message to set the body to when retracting. /// A potential fallback message to set the body to when retracting.
@ -63,7 +63,7 @@ class MessageRetractionManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<MessageRetractionData>(); final data = extensions.get<MessageRetractionData>();
return data != null return data != null
? [ ? [

View File

@ -8,7 +8,7 @@ import 'package:moxxmpp/src/stanza.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
class MessageReactions { class MessageReactions implements StanzaHandlerExtension {
const MessageReactions(this.messageId, this.emojis); const MessageReactions(this.messageId, this.emojis);
final String messageId; final String messageId;
final List<String> emojis; final List<String> emojis;
@ -69,7 +69,7 @@ class MessageReactionsManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<MessageReactions>(); final data = extensions.get<MessageReactions>();
return data != null return data != null
? [ ? [

View File

@ -73,7 +73,7 @@ List<StatelessFileSharingSource> processStatelessFileSharingSources(
return sources; return sources;
} }
class StatelessFileSharingData { class StatelessFileSharingData implements StanzaHandlerExtension {
const StatelessFileSharingData( const StatelessFileSharingData(
this.metadata, this.metadata,
this.sources, { this.sources, {
@ -140,7 +140,7 @@ class SFSManager extends XmppManagerBase {
@override @override
Future<bool> isSupported() async => true; Future<bool> isSupported() async => true;
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<StatelessFileSharingData>(); final data = extensions.get<StatelessFileSharingData>();
if (data == null) { if (data == null) {
return []; return [];

View File

@ -229,7 +229,7 @@ class StickerPack {
} }
} }
class StickersData { class StickersData implements StanzaHandlerExtension {
const StickersData(this.stickerPackId, this.sticker); const StickersData(this.stickerPackId, this.sticker);
/// The id of the sticker pack the referenced sticker is from. /// The id of the sticker pack the referenced sticker is from.
@ -270,7 +270,7 @@ class StickersManager extends XmppManagerBase {
); );
} }
List<XMLNode> _messageSendingCallback(TypedMap extensions) { List<XMLNode> _messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<StickersData>(); final data = extensions.get<StickersData>();
return data != null return data != null
? [ ? [

View File

@ -11,7 +11,7 @@ import 'package:moxxmpp/src/stringxml.dart';
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
/// A reply to a message. /// A reply to a message.
class ReplyData { class ReplyData implements StanzaHandlerExtension {
const ReplyData( const ReplyData(
this.id, { this.id, {
this.body, this.body,
@ -103,7 +103,7 @@ class MessageRepliesManager extends XmppManagerBase {
Future<bool> isSupported() async => true; Future<bool> isSupported() async => true;
@visibleForTesting @visibleForTesting
List<XMLNode> messageSendingCallback(TypedMap extensions) { List<XMLNode> messageSendingCallback(TypedMap<StanzaHandlerExtension> extensions) {
final data = extensions.get<ReplyData>(); final data = extensions.get<ReplyData>();
return data != null return data != null
? [ ? [

View File

@ -1,12 +1,14 @@
import 'package:moxxmpp/src/util/typed_map.dart'; import 'package:moxxmpp/src/util/typed_map.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
class TestType1 { abstract class BaseType {}
class TestType1 implements BaseType {
const TestType1(this.i); const TestType1(this.i);
final int i; final int i;
} }
class TestType2 { class TestType2 implements BaseType {
const TestType2(this.j); const TestType2(this.j);
final bool j; final bool j;
} }
@ -14,7 +16,7 @@ class TestType2 {
void main() { void main() {
test('Test storing data in the type map', () { test('Test storing data in the type map', () {
// Set // Set
final map = TypedMap() final map = TypedMap<BaseType>()
..set(const TestType1(1)) ..set(const TestType1(1))
..set(const TestType2(false)); ..set(const TestType2(false));