mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(mobile): show full channel history when deletion events dominate (#442)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -62,7 +62,7 @@ class ChannelMessagesNotifier extends Notifier<AsyncValue<List<NostrEvent>>> {
|
||||
tags: {
|
||||
'#h': [channelId],
|
||||
},
|
||||
limit: 50,
|
||||
limit: 200,
|
||||
),
|
||||
_handleLiveEvent,
|
||||
);
|
||||
@@ -87,7 +87,7 @@ class ChannelMessagesNotifier extends Notifier<AsyncValue<List<NostrEvent>>> {
|
||||
tags: {
|
||||
'#h': [channelId],
|
||||
},
|
||||
limit: 50,
|
||||
limit: 200,
|
||||
),
|
||||
);
|
||||
if (!_isCurrentInit(initVersion)) {
|
||||
@@ -106,6 +106,12 @@ class ChannelMessagesNotifier extends Notifier<AsyncValue<List<NostrEvent>>> {
|
||||
merged.sort((a, b) => a.createdAt.compareTo(b.createdAt));
|
||||
_lastKnownMessages = merged;
|
||||
state = AsyncData(merged);
|
||||
|
||||
// Auto-prefetch: if deletions/reactions crowded out displayable messages,
|
||||
// loop fetchOlder() until we have enough content to fill the screen.
|
||||
// Must clear _initInFlight first so fetchOlder() doesn't short-circuit.
|
||||
_initInFlight = false;
|
||||
await _ensureMinDisplayable(initVersion);
|
||||
} catch (e, st) {
|
||||
if (!_isCurrentInit(initVersion)) {
|
||||
return;
|
||||
@@ -146,6 +152,37 @@ class ChannelMessagesNotifier extends Notifier<AsyncValue<List<NostrEvent>>> {
|
||||
content.contains('member_removed');
|
||||
}
|
||||
|
||||
/// Kinds that are metadata rather than displayable content (deletions,
|
||||
/// reactions, edits, legacy pre-migration messages).
|
||||
static const _metadataKinds = {5, 7, 40001, 40003};
|
||||
|
||||
/// Minimum displayable messages we want after the initial history load.
|
||||
static const _minDisplayable = 15;
|
||||
|
||||
/// Max extra fetchOlder rounds during auto-prefetch to avoid hammering the
|
||||
/// relay.
|
||||
static const _maxPrefetchRounds = 3;
|
||||
|
||||
/// After the initial history fetch, check whether enough user-visible
|
||||
/// messages were loaded. If deletion/reaction events consumed most of the
|
||||
/// fetch limit, loop [fetchOlder] to backfill displayable content.
|
||||
Future<void> _ensureMinDisplayable(int initVersion) async {
|
||||
for (var i = 0; i < _maxPrefetchRounds; i++) {
|
||||
if (!_isCurrentInit(initVersion) || _reachedOldest) return;
|
||||
|
||||
final events = state.value;
|
||||
if (events == null) return;
|
||||
|
||||
final displayable = events
|
||||
.where((e) => !_metadataKinds.contains(e.kind))
|
||||
.length;
|
||||
if (displayable >= _minDisplayable) return;
|
||||
|
||||
final loaded = await fetchOlder();
|
||||
if (!loaded) return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge a new event into the sorted list, deduplicating by ID.
|
||||
static List<NostrEvent> _mergeEvent(
|
||||
List<NostrEvent> current,
|
||||
@@ -184,7 +221,7 @@ class ChannelMessagesNotifier extends Notifier<AsyncValue<List<NostrEvent>>> {
|
||||
tags: {
|
||||
'#h': [channelId],
|
||||
},
|
||||
limit: 50,
|
||||
limit: 100,
|
||||
until: oldest,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -34,18 +34,20 @@ void main() {
|
||||
.read(channelMessagesProvider(_channelId))
|
||||
.value!;
|
||||
expect(messages.map((event) => event.id), ['history', 'live']);
|
||||
expect(relaySession.operations, ['subscribe', 'fetch']);
|
||||
// The auto-prefetch fires an extra fetchOlder because fewer than 15
|
||||
// displayable events were loaded. The deduped result sets _reachedOldest.
|
||||
expect(relaySession.operations, ['subscribe', 'fetch', 'fetch']);
|
||||
expect(
|
||||
relaySession.liveFilters.single.kinds,
|
||||
EventKind.channelEventKinds,
|
||||
);
|
||||
expect(relaySession.liveFilters.single.tags['#h'], [_channelId]);
|
||||
expect(relaySession.liveFilters.single.limit, 50);
|
||||
expect(relaySession.liveFilters.single.limit, 200);
|
||||
expect(
|
||||
relaySession.historyFilters.single.kinds,
|
||||
relaySession.historyFilters.first.kinds,
|
||||
EventKind.channelEventKinds,
|
||||
);
|
||||
expect(relaySession.historyFilters.single.tags['#h'], [_channelId]);
|
||||
expect(relaySession.historyFilters.first.tags['#h'], [_channelId]);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -62,7 +64,7 @@ void main() {
|
||||
|
||||
final messages = container.read(channelMessagesProvider(_channelId)).value!;
|
||||
expect(messages.map((event) => event.id), ['history']);
|
||||
expect(relaySession.operations, ['subscribe', 'fetch']);
|
||||
expect(relaySession.operations, ['subscribe', 'fetch', 'fetch']);
|
||||
});
|
||||
|
||||
test(
|
||||
|
||||
Reference in New Issue
Block a user