mirror of
https://github.com/block/buzz.git
synced 2026-11-02 07:22:55 +00:00
fix(mobile): preserve failed member selections
Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz> Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz
This commit is contained in:
@@ -69,6 +69,7 @@ class AddChannelMembersSheet extends HookConsumerWidget {
|
||||
|
||||
Future<void> addSelectedMembers() async {
|
||||
if (selectedUsers.value.isEmpty || isSubmitting.value) return;
|
||||
final submittedUsers = List<DirectoryUser>.of(selectedUsers.value);
|
||||
isSubmitting.value = true;
|
||||
submitError.value = null;
|
||||
try {
|
||||
@@ -76,10 +77,17 @@ class AddChannelMembersSheet extends HookConsumerWidget {
|
||||
.read(channelActionsProvider)
|
||||
.addMembers(
|
||||
channelId: channelId,
|
||||
pubkeys: selectedUsers.value.map((user) => user.pubkey).toList(),
|
||||
pubkeys: submittedUsers.map((user) => user.pubkey).toList(),
|
||||
);
|
||||
if (context.mounted) Navigator.of(context).pop(true);
|
||||
} on AddMembersException catch (error) {
|
||||
final failedPubkeys = error.failures.keys
|
||||
.map((pubkey) => pubkey.toLowerCase())
|
||||
.toSet();
|
||||
selectedUsers.value = [
|
||||
for (final user in submittedUsers)
|
||||
if (failedPubkeys.contains(user.pubkey.toLowerCase())) user,
|
||||
];
|
||||
submitError.value = error.message;
|
||||
} catch (error) {
|
||||
submitError.value = error.toString();
|
||||
|
||||
@@ -1140,6 +1140,96 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'keeps only rejected members selected after a partial failure',
|
||||
(tester) async {
|
||||
var attempts = 0;
|
||||
final submittedPubkeys = <List<String>>[];
|
||||
await tester.pumpWidget(
|
||||
_buildTestable(
|
||||
messages: const [],
|
||||
members: [
|
||||
ChannelMember(
|
||||
pubkey: 'self',
|
||||
role: 'owner',
|
||||
joinedAt: DateTime(2025),
|
||||
),
|
||||
],
|
||||
directoryUsers: const [
|
||||
DirectoryUser(pubkey: 'alice', displayName: 'Alice'),
|
||||
DirectoryUser(pubkey: 'bob', displayName: 'Bob'),
|
||||
],
|
||||
createChannelActions: (ref) => _FakeChannelActions(
|
||||
ref,
|
||||
onAddMembers: (_, pubkeys) async {
|
||||
submittedPubkeys.add(pubkeys);
|
||||
attempts += 1;
|
||||
if (attempts == 1) {
|
||||
throw const AddMembersException({'bob': 'rejected'});
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(
|
||||
find.byKey(const ValueKey('channel-header-settings-trigger')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(
|
||||
find.byKey(const ValueKey('channel-details-add-members-row')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(
|
||||
find.byKey(const ValueKey('add-channel-member-alice')),
|
||||
);
|
||||
await tester.pump();
|
||||
await tester.tap(find.byKey(const ValueKey('add-channel-member-bob')));
|
||||
await tester.pump();
|
||||
expect(
|
||||
find.byKey(const ValueKey('add-channel-member-selected-alice')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const ValueKey('add-channel-member-selected-bob')),
|
||||
findsOneWidget,
|
||||
);
|
||||
await tester.tap(
|
||||
find.byKey(const ValueKey('add-channel-members-submit')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(attempts, 1);
|
||||
expect(
|
||||
find.byKey(const ValueKey('add-channel-member-selected-alice')),
|
||||
findsNothing,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const ValueKey('add-channel-member-selected-bob')),
|
||||
findsOneWidget,
|
||||
);
|
||||
// The successful add must not remain selected for a retry.
|
||||
expect(
|
||||
tester
|
||||
.widgetList<InputChip>(find.byType(InputChip))
|
||||
.map((chip) => chip.key)
|
||||
.toList(),
|
||||
[const ValueKey('add-channel-member-selected-bob')],
|
||||
);
|
||||
await tester.tap(
|
||||
find.byKey(const ValueKey('add-channel-members-submit')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(attempts, 2);
|
||||
expect(submittedPubkeys, [
|
||||
['alice', 'bob'],
|
||||
['bob'],
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('hides composer for archived channels', (tester) async {
|
||||
final archivedChannel = _testChannel.copyWith(
|
||||
archivedAt: DateTime.utc(2025, 1, 2),
|
||||
|
||||
Reference in New Issue
Block a user