fix(mobile): push every message in your own Solo chats

Solo chats are private streams, not DMs, so the push lease only covered
them through explicit mentions. Subscribe channel-wide to the viewer's own
joined Solo chats, matching the Solo tab's predicate.

Signed-off-by: Tom Brow <tomb@block.xyz>
This commit is contained in:
Tom Brow
2026-10-26 18:53:37 -07:00
parent 8216db1c71
commit 41549e685d
2 changed files with 66 additions and 18 deletions

View File

@@ -50,12 +50,15 @@ List<BuzzPushSubscription>? desiredBuzzPushSubscriptions({
return buildDesiredBuzzPushSubscriptions(
myPubkey: pubkey,
channelIds: [
// Activity surfaces channel-wide traffic only for joined DM channels.
// Other message kinds enter the inbox through an exact #p mention or
// participant-thread tag, so subscribing to every joined channel would
// over-notify compared with the product predicate.
// Channel-wide traffic pushes only for joined DMs and the viewer's own
// Solo chats, which are conversations with them. Other channels push
// through an exact #p mention, so subscribing to every joined channel
// would over-notify.
for (final channel in channels)
if (channel.isDm && channel.isMember && !channel.isArchived) channel.id,
if ((channel.isDm || channel.isPersonalChat(pubkey, const [])) &&
channel.isMember &&
!channel.isArchived)
channel.id,
],
mutedChannelIds: mutedChannelIds,
);

View File

@@ -37,6 +37,43 @@ void main() {
},
);
test('subscribes channel-wide to joined DMs and own Solo chats only', () {
final keys = nostr.Keys.generate();
const dmID = '123e4567-e89b-42d3-a456-426614174003';
const soloID = '123e4567-e89b-42d3-a456-426614174004';
const archivedSoloID = '123e4567-e89b-42d3-a456-426614174005';
const otherSoloID = '123e4567-e89b-42d3-a456-426614174006';
const streamID = '123e4567-e89b-42d3-a456-426614174007';
Channel solo(String id, {String? createdBy, bool archived = false}) =>
channel(
id,
channelType: 'stream',
visibility: 'private',
labels: const ['buzz.solo'],
createdBy: createdBy ?? keys.public,
archived: archived,
);
final subscriptions = desiredBuzzPushSubscriptions(
community: Community.create(
name: 'Team',
relayUrl: 'https://relay.example.com',
nsec: keys.nsec,
),
channels: [
channel(dmID),
solo(soloID),
solo(archivedSoloID, archived: true),
solo(otherSoloID, createdBy: 'author'),
channel(streamID, channelType: 'stream', visibility: 'private'),
],
mutedChannelIds: const [],
);
expect(subscriptions, hasLength(2));
expect(subscriptions!.last.filter.kinds, buzzPushChannelKinds);
expect(subscriptions.last.filter.hTags, [dmID, soloID]);
});
test('returns no desired subscriptions without a signing identity', () {
final subscriptions = desiredBuzzPushSubscriptions(
community: Community.create(
@@ -51,16 +88,24 @@ void main() {
});
}
Channel channel(String id, {bool isMember = true, bool archived = false}) =>
Channel(
id: id,
name: id,
channelType: 'dm',
visibility: 'open',
description: '',
createdBy: 'author',
createdAt: DateTime(2026),
memberCount: 1,
isMember: isMember,
archivedAt: archived ? DateTime(2026) : null,
);
Channel channel(
String id, {
bool isMember = true,
bool archived = false,
String channelType = 'dm',
String visibility = 'open',
List<String> labels = const [],
String createdBy = 'author',
}) => Channel(
id: id,
name: id,
channelType: channelType,
visibility: visibility,
labels: labels,
description: '',
createdBy: createdBy,
createdAt: DateTime(2026),
memberCount: 1,
isMember: isMember,
archivedAt: archived ? DateTime(2026) : null,
);