Skip to content

Commit e366c5e

Browse files
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. Also added two tests to verify the behaviour Fixes #1368.
1 parent e0df0ed commit e366c5e

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

lib/widgets/message_list.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10821082
?? zulipLocalizations.unknownChannelName; // TODO(log)
10831083

10841084
streamWidget = GestureDetector(
1085+
behavior: HitTestBehavior.opaque,
10851086
onTap: () => Navigator.push(context,
10861087
MessageListPage.buildRoute(context: context,
10871088
narrow: ChannelNarrow(message.streamId))),

test/widgets/message_list_test.dart

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,4 +1470,108 @@ void main() {
14701470
..status.equals(AnimationStatus.dismissed);
14711471
});
14721472
});
1473+
1474+
group('channel header navigation in multi-channel narrows', () {
1475+
testWidgets("navigates to ChannelNarrow when tapping above or below channel name in recipient header", (tester) async {
1476+
final pushedRoutes = <Route<void>>[];
1477+
final navObserver = TestNavigatorObserver()
1478+
..onPushed = (route, prevRoute) => pushedRoutes.add(route);
1479+
final channel = eg.stream();
1480+
final message = eg.streamMessage(stream: channel);
1481+
await setupMessageListPage(tester,
1482+
narrow: const CombinedFeedNarrow(),
1483+
streams: [channel],
1484+
subscriptions: [eg.subscription(channel)],
1485+
messages: [message],
1486+
navObservers: [navObserver]);
1487+
1488+
assert(pushedRoutes.length == 1);
1489+
pushedRoutes.clear();
1490+
1491+
connection.prepare(json: eg.newestGetMessagesResult(
1492+
foundOldest: true, messages: [message]).toJson());
1493+
1494+
final recipientHeaderFinder = find.byType(StreamMessageRecipientHeader);
1495+
final recipientHeaderRect = tester.getRect(recipientHeaderFinder);
1496+
1497+
final channelNameFinder = find.descendant(
1498+
of: recipientHeaderFinder,
1499+
matching: find.text(channel.name));
1500+
final channelNameRect = tester.getRect(channelNameFinder);
1501+
1502+
// First tap: 1 px below the top of recepient header at channelName x coordinate
1503+
await tester.tapAt(Offset(channelNameRect.center.dx, recipientHeaderRect.top + 1));
1504+
1505+
await tester.pump();
1506+
check(pushedRoutes).single.isA<WidgetRoute>().page.isA<MessageListPage>()
1507+
.initNarrow.equals(ChannelNarrow(channel.streamId));
1508+
await tester.pumpAndSettle();
1509+
1510+
// Navigate back to original page and clear routes
1511+
await tester.pageBack();
1512+
await tester.pumpAndSettle();
1513+
pushedRoutes.clear();
1514+
1515+
connection.prepare(json: eg.newestGetMessagesResult(
1516+
foundOldest: true, messages: [message]).toJson());
1517+
1518+
// Second tap: 1 px above the bottom of the recipient header at channelName x coordinate
1519+
await tester.tapAt(Offset(channelNameRect.center.dx, channelNameRect.bottom - 1));
1520+
await tester.pump();
1521+
check(pushedRoutes).single.isA<WidgetRoute>().page.isA<MessageListPage>()
1522+
.initNarrow.equals(ChannelNarrow(channel.streamId));
1523+
await tester.pumpAndSettle();
1524+
});
1525+
1526+
testWidgets("navigates to TopicNarrow when tapping above or below topic name in recipient header", (tester) async {
1527+
final pushedRoutes = <Route<void>>[];
1528+
final navObserver = TestNavigatorObserver()
1529+
..onPushed = (route, prevRoute) => pushedRoutes.add(route);
1530+
final channel = eg.stream();
1531+
final message = eg.streamMessage(stream: channel, topic: 'testTopic');
1532+
await setupMessageListPage(tester,
1533+
narrow: const CombinedFeedNarrow(),
1534+
streams: [channel],
1535+
subscriptions: [eg.subscription(channel)],
1536+
messages: [message],
1537+
navObservers: [navObserver]);
1538+
1539+
assert(pushedRoutes.length == 1);
1540+
pushedRoutes.clear();
1541+
1542+
connection.prepare(json: eg.newestGetMessagesResult(
1543+
foundOldest: true, messages: [message]).toJson());
1544+
1545+
final recipientHeaderFinder = find.byType(StreamMessageRecipientHeader);
1546+
final recipientHeaderRect = tester.getRect(recipientHeaderFinder);
1547+
1548+
final topicNameFinder = find.descendant(
1549+
of: recipientHeaderFinder,
1550+
matching: find.text('testTopic'));
1551+
final topicNameRect = tester.getRect(topicNameFinder);
1552+
1553+
// First tap: 1 px below the top of recepient header at topicName x coordinate
1554+
await tester.tapAt(Offset(topicNameRect.center.dx, recipientHeaderRect.top + 1));
1555+
await tester.pump();
1556+
check(pushedRoutes).single.isA<WidgetRoute>().page.isA<MessageListPage>()
1557+
.initNarrow.equals(TopicNarrow(channel.streamId, message.topic));
1558+
await tester.pumpAndSettle();
1559+
1560+
// Navigate back to original page and clear routes
1561+
await tester.pageBack();
1562+
await tester.pumpAndSettle();
1563+
pushedRoutes.clear();
1564+
1565+
connection.prepare(json: eg.newestGetMessagesResult(
1566+
foundOldest: true, messages: [message]).toJson());
1567+
1568+
// Second tap: 1 px above the bottom of the recipient header at topicName x coordinate
1569+
await tester.tapAt(Offset(topicNameRect.center.dx, recipientHeaderRect.bottom - 1));
1570+
await tester.pump();
1571+
check(pushedRoutes).single.isA<WidgetRoute>().page.isA<MessageListPage>()
1572+
.initNarrow.equals(TopicNarrow(channel.streamId, message.topic));
1573+
await tester.pumpAndSettle();
1574+
});
1575+
}
1576+
);
14731577
}

0 commit comments

Comments
 (0)