From 572b1c2d11d646ac87a192e0adc3884176f7d969 Mon Sep 17 00:00:00 2001 From: E-m-i-n-e-n-c-e Date: Fri, 21 Feb 2025 20:11:21 +0530 Subject: [PATCH] msglist: Fix channel header tap behaviour in multi-channel narrows Set gesture detecter behavior of streamWidget to HitTestBehavior.opaque to handle taps in empty space around the header. Fixes #1179. --- lib/widgets/message_list.dart | 1 + test/widgets/message_list_test.dart | 103 ++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/lib/widgets/message_list.dart b/lib/widgets/message_list.dart index c4ca22bce3..33e0941898 100644 --- a/lib/widgets/message_list.dart +++ b/lib/widgets/message_list.dart @@ -1082,6 +1082,7 @@ class StreamMessageRecipientHeader extends StatelessWidget { ?? zulipLocalizations.unknownChannelName; // TODO(log) streamWidget = GestureDetector( + behavior: HitTestBehavior.opaque, onTap: () => Navigator.push(context, MessageListPage.buildRoute(context: context, narrow: ChannelNarrow(message.streamId))), diff --git a/test/widgets/message_list_test.dart b/test/widgets/message_list_test.dart index b5d3844c1a..cb8e17bc1c 100644 --- a/test/widgets/message_list_test.dart +++ b/test/widgets/message_list_test.dart @@ -1470,4 +1470,107 @@ void main() { ..status.equals(AnimationStatus.dismissed); }); }); + + group('recipient header navigation in multi-channel narrows', () { + late List> pushedRoutes; + + final channel = eg.stream(); + const testTopic = 'testTopic'; + final message = eg.streamMessage(stream: channel, topic: testTopic); + + final recipientHeaderFinder = find.byType(StreamMessageRecipientHeader); + late Rect recipientHeaderRect; + + Future prepare(WidgetTester tester) async { + pushedRoutes = []; + final navObserver = TestNavigatorObserver() + ..onPushed = (route, prevRoute) => pushedRoutes.add(route); + + await setupMessageListPage(tester, + narrow: const CombinedFeedNarrow(), + streams: [channel], + subscriptions: [eg.subscription(channel)], + messages: [message], + navObservers: [navObserver]); + + assert(pushedRoutes.length == 1); + pushedRoutes.clear(); + + recipientHeaderRect = tester.getRect(recipientHeaderFinder); + } + + // Regression test for: https://github.com/zulip/zulip-flutter/issues/1179 + testWidgets("navigates to ChannelNarrow when tapping above or below channel name in recipient header", (tester) async { + await prepare(tester); + + final channelNameFinder = find.descendant( + of: recipientHeaderFinder, + matching: find.text(channel.name)); + final channelNameRect = tester.getRect(channelNameFinder); + + connection.prepare(json: eg.newestGetMessagesResult( + foundOldest: true, messages: [message]).toJson()); + // Tap just right below the top of recipient header, above and outside of + // its channel name component. + await tester.tapAt(Offset( + channelNameRect.center.dx, recipientHeaderRect.top + 1)); + await tester.pump(); + check(pushedRoutes).single.isA().page.isA() + .initNarrow.equals(ChannelNarrow(channel.streamId)); + await tester.pumpAndSettle(); + + // Navigate back to original page and clear routes. + await tester.pageBack(); + await tester.pumpAndSettle(); + pushedRoutes.clear(); + + connection.prepare(json: eg.newestGetMessagesResult( + foundOldest: true, messages: [message]).toJson()); + // Tap just above the bottom of recipient header, below and outside of + // its channel name component. + await tester.tapAt(Offset( + channelNameRect.center.dx, recipientHeaderRect.bottom - 1)); + await tester.pump(); + check(pushedRoutes).single.isA().page.isA() + .initNarrow.equals(ChannelNarrow(channel.streamId)); + await tester.pumpAndSettle(); + }); + + // Regression test for: https://github.com/zulip/zulip-flutter/issues/1179 + testWidgets("navigates to TopicNarrow when tapping above or below topic name in recipient header", (tester) async { + await prepare(tester); + + final topicNameFinder = find.descendant( + of: recipientHeaderFinder, + matching: find.text(testTopic)); + final topicNameRect = tester.getRect(topicNameFinder); + + connection.prepare(json: eg.newestGetMessagesResult( + foundOldest: true, messages: [message]).toJson()); + // Tap just right below the top of recipient header, above and outside of + // its topic name component. + await tester.tapAt(Offset( + topicNameRect.center.dx, recipientHeaderRect.top + 1)); + await tester.pump(); + check(pushedRoutes).single.isA().page.isA() + .initNarrow.equals(TopicNarrow(channel.streamId, message.topic)); + await tester.pumpAndSettle(); + + // Navigate back to original page and clear routes. + await tester.pageBack(); + await tester.pumpAndSettle(); + pushedRoutes.clear(); + + connection.prepare(json: eg.newestGetMessagesResult( + foundOldest: true, messages: [message]).toJson()); + // Tap just above the bottom of recipient header, below and outside of + // its topic name component. + await tester.tapAt(Offset( + topicNameRect.center.dx, recipientHeaderRect.bottom - 1)); + await tester.pump(); + check(pushedRoutes).single.isA().page.isA() + .initNarrow.equals(TopicNarrow(channel.streamId, message.topic)); + await tester.pumpAndSettle(); + }); + }); }