Skip to content

Commit 42609b1

Browse files
fix: pubkey comparisons in same format
1 parent c60bb00 commit 42609b1

File tree

12 files changed

+111
-107
lines changed

12 files changed

+111
-107
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2323
### Fixed
2424
- Fixed get user logic, to show metadata when searching a new npub
2525
- Fixes profile edition with outdated metadata
26+
- Fixes pubkeys formatting and pubkeys comparisons in different format
2627

2728
### Security
2829

lib/config/providers/chat_provider.dart

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:whitenoise/src/rust/api/error.dart' show ApiError;
1212
import 'package:whitenoise/src/rust/api/messages.dart';
1313
import 'package:whitenoise/src/rust/api/utils.dart';
1414
import 'package:whitenoise/utils/message_converter.dart';
15+
import 'package:whitenoise/utils/pubkey_formatter.dart';
1516

1617
class ChatNotifier extends Notifier<ChatState> {
1718
final _logger = Logger('ChatNotifier');
@@ -426,15 +427,25 @@ class ChatNotifier extends Notifier<ChatState> {
426427
if (gId == null) return false;
427428
final groupMessages = state.groupMessages[gId] ?? [];
428429
if (index <= 0 || index >= groupMessages.length) return false;
429-
return groupMessages[index].sender.publicKey == groupMessages[index - 1].sender.publicKey;
430+
final currentSenderPubkey = groupMessages[index].sender.publicKey;
431+
final currentSenderHexPubkey = PubkeyFormatter(pubkey: currentSenderPubkey).toHex() ?? '';
432+
final previousSenderPubkey = groupMessages[index - 1].sender.publicKey;
433+
final previousSenderHexPubkey = PubkeyFormatter(pubkey: previousSenderPubkey).toHex() ?? '';
434+
if (currentSenderHexPubkey.isEmpty || previousSenderHexPubkey.isEmpty) return false;
435+
return currentSenderHexPubkey == previousSenderHexPubkey;
430436
}
431437

432438
bool isNextSameSender(int index, {String? groupId}) {
433439
final gId = groupId ??= state.selectedGroupId;
434440
if (gId == null) return false;
435441
final groupMessages = state.groupMessages[gId] ?? [];
436442
if (index < 0 || index >= groupMessages.length - 1) return false;
437-
return groupMessages[index].sender.publicKey == groupMessages[index + 1].sender.publicKey;
443+
final currentSenderPubkey = groupMessages[index].sender.publicKey;
444+
final currentSenderHexPubkey = PubkeyFormatter(pubkey: currentSenderPubkey).toHex() ?? '';
445+
final nextSenderPubkey = groupMessages[index + 1].sender.publicKey;
446+
final nextSenderHexPubkey = PubkeyFormatter(pubkey: nextSenderPubkey).toHex() ?? '';
447+
if (currentSenderHexPubkey.isEmpty || nextSenderHexPubkey.isEmpty) return false;
448+
return currentSenderHexPubkey == nextSenderHexPubkey;
438449
}
439450

440451
/// Get unread message count for a group

lib/config/providers/follows_provider.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:whitenoise/config/providers/auth_provider.dart';
77
import 'package:whitenoise/src/rust/api/accounts.dart' as accounts_api;
88
import 'package:whitenoise/src/rust/api/users.dart';
99
import 'package:whitenoise/utils/error_handling.dart';
10+
import 'package:whitenoise/utils/pubkey_formatter.dart';
1011
import 'package:whitenoise/utils/user_utils.dart';
1112

1213
class FollowsState {
@@ -197,7 +198,9 @@ class FollowsNotifier extends Notifier<FollowsState> {
197198
}
198199

199200
bool isFollowing(String pubkey) {
200-
return state.follows.any((user) => user.pubkey == pubkey);
201+
final hexPubkey = PubkeyFormatter(pubkey: pubkey).toHex();
202+
if (hexPubkey == null) return false;
203+
return state.follows.any((user) => PubkeyFormatter(pubkey: user.pubkey).toHex() == hexPubkey);
201204
}
202205

203206
List<User> get allFollows => state.follows;

lib/config/providers/group_provider.dart

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class GroupsNotifier extends Notifier<GroupsState> {
114114
await _loadGroupTypesForAllGroups(groups);
115115

116116
// Now calculate display names with member data available
117-
await _calculateDisplayNames(groups, activePubkey);
117+
await _calculateDisplayNames(groups);
118118

119119
// Schedule message loading after the current build cycle completes
120120
Future.microtask(() async {
@@ -468,13 +468,13 @@ class GroupsNotifier extends Notifier<GroupsState> {
468468
}
469469

470470
/// Calculate display names for all groups
471-
Future<void> _calculateDisplayNames(List<Group> groups, String currentUserPubkey) async {
471+
Future<void> _calculateDisplayNames(List<Group> groups) async {
472472
final Map<String, String> displayNames = Map<String, String>.from(
473473
state.groupDisplayNames ?? {},
474474
);
475475

476476
for (final group in groups) {
477-
final displayName = await _getDisplayNameForGroup(group, currentUserPubkey);
477+
final displayName = await _getDisplayNameForGroup(group);
478478
displayNames[group.mlsGroupId] = displayName;
479479
}
480480

@@ -490,7 +490,7 @@ class GroupsNotifier extends Notifier<GroupsState> {
490490
final activePubkey = ref.read(activePubkeyProvider) ?? '';
491491
if (activePubkey.isEmpty) return;
492492

493-
final displayName = await _getDisplayNameForGroup(group, activePubkey);
493+
final displayName = await _getDisplayNameForGroup(group);
494494
final updatedDisplayNames = Map<String, String>.from(state.groupDisplayNames ?? {});
495495
updatedDisplayNames[groupId] = displayName;
496496

@@ -588,13 +588,12 @@ class GroupsNotifier extends Notifier<GroupsState> {
588588
}
589589

590590
/// Get the appropriate display name for a group
591-
Future<String> _getDisplayNameForGroup(Group group, String currentUserPubkey) async {
591+
Future<String> _getDisplayNameForGroup(Group group) async {
592592
// For direct messages, use the other member's name
593593
final groupInformation = await getGroupInformation(groupId: group.mlsGroupId);
594594
if (groupInformation.groupType == GroupType.directMessage) {
595595
try {
596-
final currentUserNpub = PubkeyFormatter(pubkey: currentUserPubkey).toNpub();
597-
final otherMember = getOtherGroupMember(group.mlsGroupId, currentUserNpub);
596+
final otherMember = getOtherGroupMember(group.mlsGroupId);
598597

599598
if (otherMember == null) {
600599
_logger.warning(
@@ -804,7 +803,7 @@ class GroupsNotifier extends Notifier<GroupsState> {
804803
await _loadGroupTypesForAllGroups(actuallyNewGroups);
805804

806805
// Calculate display names for new groups
807-
await _calculateDisplayNamesForSpecificGroups(actuallyNewGroups, activePubkey);
806+
await _calculateDisplayNamesForSpecificGroups(actuallyNewGroups);
808807

809808
_logger.info('GroupsProvider: Added ${actuallyNewGroups.length} new groups');
810809
}
@@ -852,14 +851,13 @@ class GroupsNotifier extends Notifier<GroupsState> {
852851
/// Calculate display names for specific groups (used for new groups)
853852
Future<void> _calculateDisplayNamesForSpecificGroups(
854853
List<Group> groups,
855-
String currentUserPubkey,
856854
) async {
857855
final Map<String, String> displayNames = Map<String, String>.from(
858856
state.groupDisplayNames ?? {},
859857
);
860858

861859
for (final group in groups) {
862-
final displayName = await _getDisplayNameForGroup(group, currentUserPubkey);
860+
final displayName = await _getDisplayNameForGroup(group);
863861
displayNames[group.mlsGroupId] = displayName;
864862
}
865863

@@ -1025,18 +1023,25 @@ final groupsProvider = NotifierProvider<GroupsNotifier, GroupsState>(
10251023
);
10261024

10271025
extension GroupMemberUtils on GroupsNotifier {
1028-
User? getOtherGroupMember(String? groupId, String? currentUserNpub) {
1029-
if (groupId == null || currentUserNpub == null) return null;
1026+
User? getOtherGroupMember(String? groupId) {
1027+
if (groupId == null) return null;
1028+
final activePubkey = ref.read(activePubkeyProvider);
1029+
if (activePubkey == null || activePubkey.isEmpty) return null;
10301030
final members = getGroupMembers(groupId);
10311031
if (members == null || members.isEmpty) return null;
10321032

1033-
// Use safe filtering - never return the current user as fallback
1034-
final otherMembers = members.where((member) => member.publicKey != currentUserNpub).toList();
1035-
1033+
final hexActivePubkey = PubkeyFormatter(pubkey: activePubkey).toHex();
1034+
final otherMembers =
1035+
members
1036+
.where(
1037+
(member) => PubkeyFormatter(pubkey: member.publicKey).toHex() != hexActivePubkey,
1038+
)
1039+
.toList();
1040+
final npubActivePubkey = PubkeyFormatter(pubkey: activePubkey).toNpub();
10361041
if (otherMembers.isEmpty) {
10371042
_logger.warning(
10381043
'GroupsProvider: No other members found in DM group $groupId. '
1039-
'Total members: ${members.length}, Current user: $currentUserNpub',
1044+
'Total members: ${members.length}, Current user: $npubActivePubkey',
10401045
);
10411046
return null;
10421047
}
@@ -1047,7 +1052,7 @@ extension GroupMemberUtils on GroupsNotifier {
10471052
/// Get the display image for a group based on its type
10481053
/// For direct messages, returns the other member's image
10491054
/// For regular groups, returns null (can be extended for group avatars)
1050-
String? getGroupDisplayImage(String groupId, String currentUserNpub) {
1055+
String? getGroupDisplayImage(String groupId) {
10511056
final group = findGroupById(groupId);
10521057
if (group == null) return null;
10531058

@@ -1063,7 +1068,7 @@ extension GroupMemberUtils on GroupsNotifier {
10631068

10641069
// For direct messages, use the other member's image
10651070
if (groupType == GroupType.directMessage) {
1066-
final otherMember = getOtherGroupMember(groupId, currentUserNpub);
1071+
final otherMember = getOtherGroupMember(groupId);
10671072
return otherMember?.imagePath;
10681073
}
10691074

lib/domain/models/contact_model.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ class ContactModel {
7272
bool operator ==(covariant ContactModel other) {
7373
if (identical(this, other)) return true;
7474

75-
return other.publicKey == publicKey &&
75+
final hexNpub = PubkeyFormatter(pubkey: publicKey).toHex();
76+
final otherHexNpub = PubkeyFormatter(pubkey: other.publicKey).toHex();
77+
78+
return hexNpub == otherHexNpub &&
7679
other.imagePath == imagePath &&
7780
other.displayName == displayName &&
7881
other.about == about &&

lib/domain/services/dm_chat_service.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import 'package:flutter_riverpod/flutter_riverpod.dart';
2-
import 'package:whitenoise/config/providers/active_pubkey_provider.dart';
32
import 'package:whitenoise/config/providers/group_provider.dart';
43
import 'package:whitenoise/domain/models/contact_model.dart';
54
import 'package:whitenoise/domain/models/dm_chat_data.dart';
@@ -9,15 +8,10 @@ import 'package:whitenoise/utils/pubkey_formatter.dart';
98
class DMChatService {
109
static Future<DMChatData?> getDMChatData(String groupId, WidgetRef ref) async {
1110
try {
12-
final activePubkey = ref.read(activePubkeyProvider) ?? '';
13-
if (activePubkey.isEmpty) return null;
14-
15-
final currentUserNpub = PubkeyFormatter(pubkey: activePubkey).toNpub();
1611
final otherMember = ref
1712
.read(groupsProvider.notifier)
1813
.getOtherGroupMember(
1914
groupId,
20-
currentUserNpub,
2115
);
2216

2317
if (otherMember != null) {

lib/ui/chat/chat_info/dm_chat_info.dart

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,9 @@ class _DMChatInfoState extends ConsumerState<DMChatInfo> {
3535
Future<void> _loadContact() async {
3636
final activePubkey = ref.read(activePubkeyProvider) ?? '';
3737
if (activePubkey.isNotEmpty) {
38-
final currentUserNpub = PubkeyFormatter(pubkey: activePubkey).toNpub() ?? '';
39-
final otherMember = ref
40-
.read(groupsProvider.notifier)
41-
.getOtherGroupMember(widget.groupId, currentUserNpub);
38+
final otherMember = ref.read(groupsProvider.notifier).getOtherGroupMember(widget.groupId);
4239
if (otherMember != null && mounted) {
43-
otherUserNpub = PubkeyFormatter(pubkey: otherMember.publicKey).toNpub() ?? '';
40+
otherUserNpub = PubkeyFormatter(pubkey: otherMember.publicKey).toNpub();
4441
_checkFollowStatus(otherMember.publicKey);
4542
}
4643
}

lib/ui/chat/chat_info/group_chat_info.dart

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,30 @@ class _GroupChatInfoState extends ConsumerState<GroupChatInfo> {
5656
allMembers.addAll(members);
5757

5858
for (final admin in admins) {
59-
if (!members.any((member) => member.publicKey == admin.publicKey)) {
59+
if (!members.any((member) {
60+
final hexMemberKey = PubkeyFormatter(pubkey: member.publicKey).toHex();
61+
final hexAdminKey = PubkeyFormatter(pubkey: admin.publicKey).toHex();
62+
return hexMemberKey == hexAdminKey;
63+
})) {
6064
allMembers.add(admin);
6165
}
6266
}
6367

6468
// Sort members: admins first (A-Z), then regular members (A-Z), current user last
6569
allMembers.sort((a, b) {
66-
final aIsAdmin = admins.any((admin) => admin.publicKey == a.publicKey);
67-
final bIsAdmin = admins.any((admin) => admin.publicKey == b.publicKey);
68-
final aIsCurrentUser = currentUserNpub != null && currentUserNpub == a.publicKey;
69-
final bIsCurrentUser = currentUserNpub != null && currentUserNpub == b.publicKey;
70+
final hexPubkeyA = PubkeyFormatter(pubkey: a.publicKey).toHex();
71+
final hexPubkeyB = PubkeyFormatter(pubkey: b.publicKey).toHex();
72+
final hexCurrentUserNpub = PubkeyFormatter(pubkey: currentUserNpub).toHex();
73+
final aIsAdmin = admins.any((admin) {
74+
final hexAdminKey = PubkeyFormatter(pubkey: admin.publicKey).toHex();
75+
return hexAdminKey == hexPubkeyA;
76+
});
77+
final bIsAdmin = admins.any((admin) {
78+
final hexAdminKey = PubkeyFormatter(pubkey: admin.publicKey).toHex();
79+
return hexAdminKey == hexPubkeyB;
80+
});
81+
final aIsCurrentUser = currentUserNpub != null && (hexCurrentUserNpub == hexPubkeyA);
82+
final bIsCurrentUser = currentUserNpub != null && (hexCurrentUserNpub == hexPubkeyB);
7083

7184
// Current user always goes last
7285
if (aIsCurrentUser) return 1;
@@ -216,8 +229,15 @@ class _GroupChatInfoState extends ConsumerState<GroupChatInfo> {
216229
}
217230

218231
Widget _buildMemberListTile(User member, {String? currentUserNpub}) {
219-
final isAdmin = groupAdmins.any((admin) => admin.publicKey == member.publicKey);
220-
final isCurrentUser = currentUserNpub != null && currentUserNpub == member.publicKey;
232+
final isAdmin = groupAdmins.any((admin) {
233+
final hexAdminKey = PubkeyFormatter(pubkey: admin.publicKey).toHex();
234+
final hexMemberKey = PubkeyFormatter(pubkey: member.publicKey).toHex();
235+
return hexAdminKey == hexMemberKey;
236+
});
237+
final isCurrentUser =
238+
currentUserNpub != null &&
239+
PubkeyFormatter(pubkey: currentUserNpub).toHex() ==
240+
PubkeyFormatter(pubkey: member.publicKey).toHex();
221241
return ListTile(
222242
contentPadding: EdgeInsets.symmetric(horizontal: 32.w),
223243

lib/ui/chat/chat_info/widgets/member_action_buttons.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:whitenoise/ui/core/themes/assets.dart';
1111
import 'package:whitenoise/ui/core/themes/src/extensions.dart';
1212
import 'package:whitenoise/ui/core/ui/wn_button.dart';
1313
import 'package:whitenoise/ui/core/ui/wn_image.dart';
14+
import 'package:whitenoise/utils/pubkey_formatter.dart';
1415

1516
class SendMessageButton extends ConsumerStatefulWidget {
1617
const SendMessageButton(this.user, {super.key});
@@ -110,7 +111,12 @@ class _AddToContactButtonState extends ConsumerState<AddToContactButton> {
110111
final follows = followsState.follows;
111112

112113
return follows.any(
113-
(follow) => follow.pubkey.toLowerCase() == widget.user.publicKey.toLowerCase(),
114+
(follow) {
115+
final hexFollowPubkey = PubkeyFormatter(pubkey: follow.pubkey).toHex();
116+
final hexUserPubkey = PubkeyFormatter(pubkey: widget.user.publicKey).toHex();
117+
if (hexFollowPubkey == null || hexUserPubkey == null) return false;
118+
return hexFollowPubkey == hexUserPubkey;
119+
},
114120
);
115121
}
116122

lib/ui/contact_list/widgets/chat_list_item_tile.dart

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_riverpod/flutter_riverpod.dart';
33
import 'package:gap/gap.dart';
44
import 'package:whitenoise/config/providers/group_provider.dart';
5-
import 'package:whitenoise/config/providers/nostr_keys_provider.dart';
65
import 'package:whitenoise/domain/models/chat_list_item.dart';
76
import 'package:whitenoise/domain/models/dm_chat_data.dart';
87
import 'package:whitenoise/domain/models/message_model.dart';
@@ -50,12 +49,8 @@ class ChatListItemTile extends ConsumerWidget {
5049
builder: (context, snapshot) {
5150
if (snapshot.connectionState == ConnectionState.waiting) {
5251
// Show loading state with basic info while determining group type
53-
final currentUserNpub = ref.watch(nostrKeysProvider).npub ?? '';
5452
final displayName = groupsNotifier.getGroupDisplayName(group.mlsGroupId) ?? group.name;
55-
final displayImage = groupsNotifier.getGroupDisplayImage(
56-
group.mlsGroupId,
57-
currentUserNpub,
58-
);
53+
final displayImage = groupsNotifier.getGroupDisplayImage(group.mlsGroupId);
5954
return _buildChatTileContent(context, displayName, displayImage, group);
6055
}
6156

@@ -89,12 +84,8 @@ class ChatListItemTile extends ConsumerWidget {
8984
final data = snapshot.data;
9085
if (data == null) {
9186
// Fallback to existing logic if no data
92-
final currentUserNpub = ref.watch(nostrKeysProvider).npub ?? '';
9387
final displayName = groupsNotifier.getGroupDisplayName(group.mlsGroupId) ?? group.name;
94-
final displayImage = groupsNotifier.getGroupDisplayImage(
95-
group.mlsGroupId,
96-
currentUserNpub,
97-
);
88+
final displayImage = groupsNotifier.getGroupDisplayImage(group.mlsGroupId);
9889
return _buildChatTileContent(context, displayName, displayImage, group);
9990
}
10091

@@ -103,10 +94,8 @@ class ChatListItemTile extends ConsumerWidget {
10394
);
10495
}
10596

106-
// For regular groups, use existing logic
107-
final currentUserNpub = ref.watch(nostrKeysProvider).npub ?? '';
10897
final displayName = groupsNotifier.getGroupDisplayName(group.mlsGroupId) ?? group.name;
109-
final displayImage = groupsNotifier.getGroupDisplayImage(group.mlsGroupId, currentUserNpub);
98+
final displayImage = groupsNotifier.getGroupDisplayImage(group.mlsGroupId);
11099

111100
return _buildChatTileContent(context, displayName, displayImage, group);
112101
}

0 commit comments

Comments
 (0)