@@ -11,14 +11,16 @@ import 'package:whitenoise/config/providers/group_provider.dart';
1111import 'package:whitenoise/config/states/chat_state.dart' ;
1212import 'package:whitenoise/domain/models/message_model.dart' ;
1313import 'package:whitenoise/domain/services/message_merger_service.dart' ;
14+ import 'package:whitenoise/domain/services/message_sender_service.dart' ;
15+ import 'package:whitenoise/domain/services/reaction_comparison_service.dart' ;
1416import 'package:whitenoise/src/rust/api/error.dart' show ApiError;
1517import 'package:whitenoise/src/rust/api/messages.dart' ;
16- import 'package:whitenoise/src/rust/api/utils.dart' ;
1718import 'package:whitenoise/utils/message_converter.dart' ;
1819import 'package:whitenoise/utils/pubkey_formatter.dart' ;
1920
2021class ChatNotifier extends Notifier <ChatState > {
2122 final _logger = Logger ('ChatNotifier' );
23+ final _messageSenderService = MessageSenderService ();
2224
2325 @override
2426 ChatState build () {
@@ -148,11 +150,10 @@ class ChatNotifier extends Notifier<ChatState> {
148150 try {
149151 _logger.info ('ChatProvider: Sending message to group $groupId ' );
150152
151- final sentMessage = await sendMessageToGroup (
153+ final sentMessage = await _messageSenderService. sendMessage (
152154 pubkey: activePubkey,
153155 groupId: groupId,
154- message: message,
155- kind: kind,
156+ content: message,
156157 tags: tags,
157158 );
158159
@@ -282,8 +283,7 @@ class ChatNotifier extends Notifier<ChatState> {
282283
283284 // Compare message content and reactions
284285 if (newMsg.content != currentMsg.content ||
285- newMsg.reactions.length != currentMsg.reactions.length ||
286- ! _areReactionsEqual (newMsg.reactions, currentMsg.reactions)) {
286+ ReactionComparisonService .areDifferent (newMsg.reactions, currentMsg.reactions)) {
287287 hasChanges = true ;
288288 break ;
289289 }
@@ -487,33 +487,15 @@ class ChatNotifier extends Notifier<ChatState> {
487487
488488 _logger.info ('ChatProvider: Adding reaction "$reaction " to message ${message .id }' );
489489
490- // Create reaction content (emoji) - NIP-25 compliant
491- final reactionContent = reaction; // This should be an emoji like 👍, ❤️, etc.
492-
493490 // Use the message's actual kind (now stored in MessageModel)
494491 final originalMessageKind = messageKind ?? message.kind;
495-
496- // NIP-25 compliant reaction tags
497- // According to NIP-25:
498- // - MUST have e tag with event id being reacted to
499- // - SHOULD have p tag with pubkey of event being reacted to
500- // - SHOULD have k tag with stringified kind number of reacted event
501- final reactionTags = [
502- // e tag: ["e", <event-id>]
503- await tagFromVec (vec: ['e' , message.id]),
504- // p tag: ["p", <pubkey>, <relay-hint>]
505- await tagFromVec (vec: ['p' , message.sender.publicKey, '' ]),
506- // k tag: ["k", <kind-number>]
507- await tagFromVec (vec: ['k' , originalMessageKind.toString ()]),
508- ];
509-
510- // Send reaction message (kind 7 for reactions in Nostr)
511- await sendMessageToGroup (
492+ await _messageSenderService.sendReaction (
512493 pubkey: activePubkey,
513494 groupId: message.groupId ?? '' ,
514- message: reactionContent,
515- kind: 7 , // Nostr kind 7 = reaction
516- tags: reactionTags,
495+ messageId: message.id,
496+ messagePubkey: message.sender.publicKey,
497+ messageKind: originalMessageKind,
498+ emoji: reaction,
517499 );
518500
519501 // Refresh messages to get updated reactions
@@ -581,17 +563,11 @@ class ChatNotifier extends Notifier<ChatState> {
581563 try {
582564 _logger.info ('ChatProvider: Sending reply to message $replyToMessageId ' );
583565
584- // Create tags for reply
585- final replyTags = [
586- await tagFromVec (vec: ['e' , replyToMessageId]),
587- ];
588-
589- final sentMessage = await sendMessageToGroup (
566+ final sentMessage = await _messageSenderService.sendReply (
590567 pubkey: activePubkey,
591568 groupId: groupId,
592- message: message,
593- kind: 9 ,
594- tags: replyTags,
569+ replyToMessageId: replyToMessageId,
570+ content: message,
595571 );
596572
597573 final stateMessages = state.groupMessages[groupId] ?? [];
@@ -675,20 +651,12 @@ class ChatNotifier extends Notifier<ChatState> {
675651
676652 _logger.info ('ChatProvider: Deleting message $messageId ' );
677653
678- // Create tags for deletion (NIP-09)
679- final deleteTags = [
680- await tagFromVec (vec: ['e' , messageId]),
681- await tagFromVec (vec: ['p' , messagePubkey]), // Author of the message being deleted
682- await tagFromVec (vec: ['k' , messageKind.toString ()]), // Kind of the message being deleted
683- ];
684-
685- // Send deletion message using rust API
686- await sendMessageToGroup (
654+ await _messageSenderService.sendDeletion (
687655 pubkey: activePubkey,
688656 groupId: groupId,
689- message : '' , // Empty content for deletion
690- kind : 5 , // Nostr kind 5 = deletion
691- tags : deleteTags ,
657+ messageId : messageId,
658+ messagePubkey : messagePubkey,
659+ messageKind : messageKind ,
692660 );
693661
694662 // Refresh messages to get updated state
@@ -772,51 +740,6 @@ class ChatNotifier extends Notifier<ChatState> {
772740
773741 await ref.read (groupsProvider.notifier).updateGroupActivityTime (groupId, now);
774742 }
775-
776- /// Helper method to compare if two reaction lists are equal
777- bool _areReactionsEqual (List <Reaction > reactions1, List <Reaction > reactions2) {
778- if (reactions1.length != reactions2.length) {
779- return false ;
780- }
781-
782- // Create maps of emoji -> list of user public keys for comparison
783- final map1 = < String , List <String >> {};
784- final map2 = < String , List <String >> {};
785-
786- for (final reaction in reactions1) {
787- map1.putIfAbsent (reaction.emoji, () => []).add (reaction.user.publicKey);
788- }
789-
790- for (final reaction in reactions2) {
791- map2.putIfAbsent (reaction.emoji, () => []).add (reaction.user.publicKey);
792- }
793-
794- // Compare the maps
795- if (map1.keys.length != map2.keys.length) {
796- return false ;
797- }
798-
799- for (final emoji in map1.keys) {
800- if (! map2.containsKey (emoji)) {
801- return false ;
802- }
803-
804- final users1 = map1[emoji]! ..sort ();
805- final users2 = map2[emoji]! ..sort ();
806-
807- if (users1.length != users2.length) {
808- return false ;
809- }
810-
811- for (int i = 0 ; i < users1.length; i++ ) {
812- if (users1[i] != users2[i]) {
813- return false ;
814- }
815- }
816- }
817-
818- return true ;
819- }
820743}
821744
822745final chatProvider = NotifierProvider <ChatNotifier , ChatState >(
0 commit comments