mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
[BOT-1264] fix(mobile): #channel tags not tappable (#1695)
Signed-off-by: npub1shglkdhngx3hrnhf4gf8vhpqdrmeludctechdvpwd3988zzs7ncq2cmtxu <85d1fb36f341a371cee9aa12765c2068f79ff1b85e7176b02e6c4a738850f4f0@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1shglkdhngx3hrnhf4gf8vhpqdrmeludctechdvpwd3988zzs7ncq2cmtxu <85d1fb36f341a371cee9aa12765c2068f79ff1b85e7176b02e6c4a738850f4f0@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
@@ -15,6 +15,7 @@ import '../profile/user_cache_provider.dart';
|
||||
import '../profile/user_profile.dart';
|
||||
import '../forum/forum_posts_view.dart';
|
||||
import 'channel.dart';
|
||||
import 'channel_link_navigation.dart';
|
||||
import 'agent_activity/working_bots_provider.dart';
|
||||
import 'channel_management_provider.dart';
|
||||
import 'channel_messages_provider.dart';
|
||||
|
||||
@@ -115,24 +115,11 @@ class _MessageBubble extends ConsumerWidget {
|
||||
channelNames: channelNames,
|
||||
tags: message.tags,
|
||||
onChannelTap: (channelId) {
|
||||
if (channelId == currentChannelId) return;
|
||||
final channelsAsync = ref.read(channelsProvider);
|
||||
final channels = channelsAsync.hasValue
|
||||
? channelsAsync.value
|
||||
: null;
|
||||
Channel? targetChannel;
|
||||
for (final channel in channels ?? const <Channel>[]) {
|
||||
if (channel.id == channelId) {
|
||||
targetChannel = channel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetChannel == null) return;
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) =>
|
||||
ChannelDetailPage(channel: targetChannel!),
|
||||
),
|
||||
openChannelLink(
|
||||
context: context,
|
||||
ref: ref,
|
||||
channelId: channelId,
|
||||
currentChannelId: currentChannelId,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
38
mobile/lib/features/channels/channel_link_navigation.dart
Normal file
38
mobile/lib/features/channels/channel_link_navigation.dart
Normal file
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
import 'channel.dart';
|
||||
import 'channel_detail_page.dart';
|
||||
import 'channels_provider.dart';
|
||||
|
||||
void openChannelLink({
|
||||
required BuildContext context,
|
||||
required WidgetRef ref,
|
||||
required String channelId,
|
||||
required String currentChannelId,
|
||||
}) {
|
||||
if (channelId == currentChannelId) return;
|
||||
|
||||
final channelsAsync = ref.read(channelsProvider);
|
||||
final channels = channelsAsync.hasValue ? channelsAsync.value : null;
|
||||
Channel? targetChannel;
|
||||
for (final channel in channels ?? const <Channel>[]) {
|
||||
if (channel.id == channelId) {
|
||||
targetChannel = channel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetChannel == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Channel could not be opened')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => ChannelDetailPage(channel: targetChannel!),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import '../../shared/widgets/frosted_app_bar.dart';
|
||||
import '../../shared/widgets/frosted_scaffold.dart';
|
||||
import '../profile/user_cache_provider.dart';
|
||||
import '../profile/user_profile.dart';
|
||||
import 'channel_link_navigation.dart';
|
||||
import 'channel_typing_provider.dart';
|
||||
import 'thread_replies_provider.dart';
|
||||
import 'channels_provider.dart';
|
||||
@@ -468,7 +469,14 @@ class _ThreadMessage extends ConsumerWidget {
|
||||
mentionNames: mentionNames,
|
||||
channelNames: channelNames,
|
||||
tags: message.tags,
|
||||
onChannelTap: (_) {},
|
||||
onChannelTap: (targetChannelId) {
|
||||
openChannelLink(
|
||||
context: context,
|
||||
ref: ref,
|
||||
channelId: targetChannelId,
|
||||
currentChannelId: channelId,
|
||||
);
|
||||
},
|
||||
),
|
||||
if (message.reactions.isNotEmpty)
|
||||
ReactionRow(
|
||||
|
||||
@@ -10,6 +10,8 @@ import 'package:buzz/features/channels/channel_detail_page.dart';
|
||||
import 'package:buzz/features/channels/channel_management_provider.dart';
|
||||
import 'package:buzz/features/channels/channel_messages_provider.dart';
|
||||
import 'package:buzz/features/channels/channel_typing_provider.dart';
|
||||
import 'package:buzz/features/channels/thread_detail_page.dart';
|
||||
import 'package:buzz/features/channels/timeline_message.dart';
|
||||
import 'package:buzz/features/channels/channels_provider.dart';
|
||||
import 'package:buzz/features/channels/read_state/read_state_provider.dart';
|
||||
import 'package:buzz/features/profile/profile_provider.dart';
|
||||
@@ -1099,17 +1101,7 @@ void main() {
|
||||
|
||||
group('Channel links', () {
|
||||
testWidgets('tapping a channel link opens that channel', (tester) async {
|
||||
final randomChannel = Channel(
|
||||
id: 'random-channel',
|
||||
name: 'random',
|
||||
channelType: 'stream',
|
||||
visibility: 'open',
|
||||
description: 'Random discussion',
|
||||
createdBy: 'abc123',
|
||||
createdAt: DateTime(2025),
|
||||
memberCount: 3,
|
||||
isMember: true,
|
||||
);
|
||||
final randomChannel = _channel(id: 'random-channel', name: 'random');
|
||||
final observer = _TestNavigatorObserver();
|
||||
|
||||
await tester.pumpWidget(
|
||||
@@ -1137,9 +1129,107 @@ void main() {
|
||||
|
||||
expect(observer.pushCount, initialPushCount + 1);
|
||||
});
|
||||
|
||||
testWidgets('missing channel link shows an error', (tester) async {
|
||||
final randomChannel = _channel(id: 'random-channel', name: 'random');
|
||||
final channelsNotifier = _FakeChannelsNotifier([
|
||||
_testChannel,
|
||||
randomChannel,
|
||||
]);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_buildTestable(
|
||||
messages: [
|
||||
_textMsg(
|
||||
id: 'msg1',
|
||||
pubkey: 'alice',
|
||||
content: 'Take this to #random',
|
||||
createdAt: 1000,
|
||||
),
|
||||
],
|
||||
users: {
|
||||
'alice': const UserProfile(pubkey: 'alice', displayName: 'Alice'),
|
||||
},
|
||||
channelsNotifier: channelsNotifier,
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
channelsNotifier.setChannels([_testChannel]);
|
||||
await tester.tap(find.text('#random'));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('Channel could not be opened'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('tapping a channel link inside a thread opens that channel', (
|
||||
tester,
|
||||
) async {
|
||||
final randomChannel = _channel(id: 'random-channel', name: 'random');
|
||||
final observer = _TestNavigatorObserver();
|
||||
|
||||
await tester.pumpWidget(
|
||||
_buildTestable(
|
||||
messages: [
|
||||
_textMsg(
|
||||
id: 'msg1',
|
||||
pubkey: 'alice',
|
||||
content: 'Thread root #random',
|
||||
createdAt: 1000,
|
||||
),
|
||||
],
|
||||
users: {
|
||||
'alice': const UserProfile(pubkey: 'alice', displayName: 'Alice'),
|
||||
},
|
||||
channels: [_testChannel, randomChannel],
|
||||
navigatorObservers: [observer],
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final threadMessages = formatTimeline([
|
||||
_textMsg(
|
||||
id: 'msg1',
|
||||
pubkey: 'alice',
|
||||
content: 'Thread root #random',
|
||||
createdAt: 1000,
|
||||
),
|
||||
]);
|
||||
Navigator.of(tester.element(find.byType(ChannelDetailPage))).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => ThreadDetailPage(
|
||||
threadHead: threadMessages.single,
|
||||
allMessages: threadMessages,
|
||||
channelId: _channelId,
|
||||
currentPubkey: 'self',
|
||||
isMember: true,
|
||||
isArchived: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
final initialPushCount = observer.pushCount;
|
||||
|
||||
await tester.tap(find.text('#random').last);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(observer.pushCount, initialPushCount + 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Channel _channel({required String id, required String name}) => Channel(
|
||||
id: id,
|
||||
name: name,
|
||||
channelType: 'stream',
|
||||
visibility: 'open',
|
||||
description: '$name discussion',
|
||||
createdBy: 'abc123',
|
||||
createdAt: DateTime(2025),
|
||||
memberCount: 3,
|
||||
isMember: true,
|
||||
);
|
||||
|
||||
class _FakeMessagesNotifier extends ChannelMessagesNotifier {
|
||||
List<NostrEvent> _messages;
|
||||
_FakeMessagesNotifier(this._messages) : super(_channelId);
|
||||
|
||||
Reference in New Issue
Block a user