Skip to content

Commit f06675c

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. Fixes #1179.
1 parent a3313ec commit f06675c

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

lib/widgets/message_list.dart

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

12611261
streamWidget = GestureDetector(
1262+
behavior: HitTestBehavior.opaque,
12621263
onTap: () => Navigator.push(context,
12631264
MessageListPage.buildRoute(context: context,
12641265
narrow: ChannelNarrow(streamId))),

test/widgets/message_list_test.dart

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,4 +2023,107 @@ void main() {
20232023
..status.equals(AnimationStatus.dismissed);
20242024
});
20252025
});
2026+
2027+
group('recipient header navigation in multi-channel narrows', () {
2028+
late List<Route<void>> pushedRoutes;
2029+
2030+
final channel = eg.stream();
2031+
const testTopic = 'testTopic';
2032+
final message = eg.streamMessage(stream: channel, topic: testTopic);
2033+
2034+
final recipientHeaderFinder = find.byType(StreamMessageRecipientHeader);
2035+
late Rect recipientHeaderRect;
2036+
2037+
Future<void> prepare(WidgetTester tester) async {
2038+
pushedRoutes = [];
2039+
final navObserver = TestNavigatorObserver()
2040+
..onPushed = (route, prevRoute) => pushedRoutes.add(route);
2041+
2042+
await setupMessageListPage(tester,
2043+
narrow: const CombinedFeedNarrow(),
2044+
streams: [channel],
2045+
subscriptions: [eg.subscription(channel)],
2046+
messages: [message],
2047+
navObservers: [navObserver]);
2048+
2049+
assert(pushedRoutes.length == 1);
2050+
pushedRoutes.clear();
2051+
2052+
recipientHeaderRect = tester.getRect(recipientHeaderFinder);
2053+
}
2054+
2055+
// Regression test for: https://github.com/zulip/zulip-flutter/issues/1179
2056+
testWidgets("navigates to ChannelNarrow when tapping above or below channel name in recipient header", (tester) async {
2057+
await prepare(tester);
2058+
2059+
final channelNameFinder = find.descendant(
2060+
of: recipientHeaderFinder,
2061+
matching: find.text(channel.name));
2062+
final channelNameRect = tester.getRect(channelNameFinder);
2063+
2064+
connection.prepare(json: eg.newestGetMessagesResult(
2065+
foundOldest: true, messages: [message]).toJson());
2066+
// Tap just right below the top of recipient header, above and outside of
2067+
// its channel name component.
2068+
await tester.tapAt(Offset(
2069+
channelNameRect.center.dx, recipientHeaderRect.top + 1));
2070+
await tester.pump();
2071+
check(pushedRoutes).single.isA<WidgetRoute>().page.isA<MessageListPage>()
2072+
.initNarrow.equals(ChannelNarrow(channel.streamId));
2073+
await tester.pumpAndSettle();
2074+
2075+
// Navigate back to original page and clear routes.
2076+
await tester.pageBack();
2077+
await tester.pumpAndSettle();
2078+
pushedRoutes.clear();
2079+
2080+
connection.prepare(json: eg.newestGetMessagesResult(
2081+
foundOldest: true, messages: [message]).toJson());
2082+
// Tap just above the bottom of recipient header, below and outside of
2083+
// its channel name component.
2084+
await tester.tapAt(Offset(
2085+
channelNameRect.center.dx, recipientHeaderRect.bottom - 1));
2086+
await tester.pump();
2087+
check(pushedRoutes).single.isA<WidgetRoute>().page.isA<MessageListPage>()
2088+
.initNarrow.equals(ChannelNarrow(channel.streamId));
2089+
await tester.pumpAndSettle();
2090+
});
2091+
2092+
// Regression test for: https://github.com/zulip/zulip-flutter/issues/1179
2093+
testWidgets("navigates to TopicNarrow when tapping above or below topic name in recipient header", (tester) async {
2094+
await prepare(tester);
2095+
2096+
final topicNameFinder = find.descendant(
2097+
of: recipientHeaderFinder,
2098+
matching: find.text(testTopic));
2099+
final topicNameRect = tester.getRect(topicNameFinder);
2100+
2101+
connection.prepare(json: eg.newestGetMessagesResult(
2102+
foundOldest: true, messages: [message]).toJson());
2103+
// Tap just right below the top of recipient header, above and outside of
2104+
// its topic name component.
2105+
await tester.tapAt(Offset(
2106+
topicNameRect.center.dx, recipientHeaderRect.top + 1));
2107+
await tester.pump();
2108+
check(pushedRoutes).single.isA<WidgetRoute>().page.isA<MessageListPage>()
2109+
.initNarrow.equals(TopicNarrow(channel.streamId, message.topic));
2110+
await tester.pumpAndSettle();
2111+
2112+
// Navigate back to original page and clear routes.
2113+
await tester.pageBack();
2114+
await tester.pumpAndSettle();
2115+
pushedRoutes.clear();
2116+
2117+
connection.prepare(json: eg.newestGetMessagesResult(
2118+
foundOldest: true, messages: [message]).toJson());
2119+
// Tap just above the bottom of recipient header, below and outside of
2120+
// its topic name component.
2121+
await tester.tapAt(Offset(
2122+
topicNameRect.center.dx, recipientHeaderRect.bottom - 1));
2123+
await tester.pump();
2124+
check(pushedRoutes).single.isA<WidgetRoute>().page.isA<MessageListPage>()
2125+
.initNarrow.equals(TopicNarrow(channel.streamId, message.topic));
2126+
await tester.pumpAndSettle();
2127+
});
2128+
});
20262129
}

0 commit comments

Comments
 (0)