mirror of
https://github.com/block/buzz.git
synced 2026-11-02 07:22:55 +00:00
fix(mobile): load active filter activity outside Riverpod selectors
Read the channels notifier before evaluating the selector so activity history requests can run. Exercise the real provider with signed old activity and verify the seven-day filter excludes it. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
@@ -48,6 +48,7 @@ final channelFilterActivityProvider = FutureProvider.autoDispose
|
||||
.family<int?, String>((ref, channelId) async {
|
||||
// Every live message and foreground refresh updates this owner. Re-read
|
||||
// only the affected channel; never trust its unverified presentation stamp.
|
||||
final channelsNotifier = ref.watch(channelsProvider.notifier);
|
||||
ref.watch(
|
||||
channelsProvider.select(
|
||||
(value) => (
|
||||
@@ -55,7 +56,7 @@ final channelFilterActivityProvider = FutureProvider.autoDispose
|
||||
?.where((c) => c.id == channelId)
|
||||
.firstOrNull
|
||||
?.lastMessageAt,
|
||||
ref.read(channelsProvider.notifier).activityRevisionFor(channelId),
|
||||
channelsNotifier.activityRevisionFor(channelId),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import 'package:buzz/features/channels/channels_provider.dart';
|
||||
import 'package:buzz/features/channels/channel.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:buzz/features/channels/channel_filter/channel_filter_manager.dart';
|
||||
@@ -9,6 +12,57 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:nostr/nostr.dart' as nostr;
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
test(
|
||||
'activity provider reads history and excludes a quiet channel from Active',
|
||||
() async {
|
||||
final keys = nostr.Keys.generate();
|
||||
final old = DateTime.now().millisecondsSinceEpoch ~/ 1000 - 8 * 86400;
|
||||
final event = NostrEvent.fromJson(
|
||||
nostr.Event.from(
|
||||
kind: EventKind.streamMessage,
|
||||
tags: [
|
||||
['h', 'quiet-channel'],
|
||||
],
|
||||
content: 'Earlier activity',
|
||||
secretKey: nostr.Nip19.decode(payload: keys.nsec).data,
|
||||
createdAt: old,
|
||||
verify: false,
|
||||
).toMap(),
|
||||
);
|
||||
final session = _ActivitySession(event);
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
channelsProvider.overrideWith(_ActivityChannels.new),
|
||||
relaySessionProvider.overrideWith(() => session),
|
||||
],
|
||||
);
|
||||
addTearDown(container.dispose);
|
||||
await container.read(channelsProvider.future);
|
||||
final subscription = container.listen(
|
||||
channelFilterActivityProvider('quiet-channel'),
|
||||
(_, _) {},
|
||||
);
|
||||
addTearDown(subscription.close);
|
||||
final activity = await container.read(
|
||||
channelFilterActivityProvider('quiet-channel').future,
|
||||
);
|
||||
expect(session.requests, 1);
|
||||
expect(activity, old);
|
||||
expect(
|
||||
channelMatchesFilter(
|
||||
mode: ChannelFilterMode.active,
|
||||
unread: false,
|
||||
activitySeconds: activity,
|
||||
activityKnown: true,
|
||||
nowSeconds: old + 8 * 86400,
|
||||
windowSeconds: 7 * 86400,
|
||||
),
|
||||
isFalse,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'metadata wins and edits preserve reset tombstones, unknown fields and windows',
|
||||
() {
|
||||
@@ -296,3 +350,24 @@ void main() {
|
||||
expect(verifiedFilterActivity([]), isNull);
|
||||
});
|
||||
}
|
||||
|
||||
class _ActivityChannels extends ChannelsNotifier {
|
||||
@override
|
||||
Future<List<Channel>> build() async => [];
|
||||
}
|
||||
|
||||
class _ActivitySession extends RelaySessionNotifier {
|
||||
_ActivitySession(this.event);
|
||||
final NostrEvent event;
|
||||
int requests = 0;
|
||||
@override
|
||||
SessionState build() => const SessionState(status: SessionStatus.connected);
|
||||
@override
|
||||
Future<List<NostrEvent>> fetchHistory(
|
||||
NostrFilter filter, {
|
||||
Duration timeout = const Duration(seconds: 8),
|
||||
}) async {
|
||||
requests++;
|
||||
return [event];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user