Skip to content

Commit b67a5a7

Browse files
refactor: use tested classes in chat provider
1 parent facc796 commit b67a5a7

File tree

1 file changed

+18
-95
lines changed

1 file changed

+18
-95
lines changed

lib/config/providers/chat_provider.dart

Lines changed: 18 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import 'package:whitenoise/config/providers/group_provider.dart';
1111
import 'package:whitenoise/config/states/chat_state.dart';
1212
import 'package:whitenoise/domain/models/message_model.dart';
1313
import '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';
1416
import 'package:whitenoise/src/rust/api/error.dart' show ApiError;
1517
import 'package:whitenoise/src/rust/api/messages.dart';
16-
import 'package:whitenoise/src/rust/api/utils.dart';
1718
import 'package:whitenoise/utils/message_converter.dart';
1819
import 'package:whitenoise/utils/pubkey_formatter.dart';
1920

2021
class 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

822745
final chatProvider = NotifierProvider<ChatNotifier, ChatState>(

0 commit comments

Comments
 (0)