From 9043c5fd2e567fe400d218970f9d90c8624bddaa Mon Sep 17 00:00:00 2001 From: chungwwei Date: Sat, 25 Oct 2025 21:07:57 -0400 Subject: [PATCH 1/3] all_channels: Make row item at least 44px tall with ConstrainedBox Make sure every row is at least 44px in height by specifying BoxConstraints(minHeight: 44) to meet touch target requirement. --- lib/widgets/all_channels.dart | 45 +++++++++++++++-------------- test/widgets/all_channels_test.dart | 3 ++ 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/lib/widgets/all_channels.dart b/lib/widgets/all_channels.dart index 3aaf0d8baf..cda1969a87 100644 --- a/lib/widgets/all_channels.dart +++ b/lib/widgets/all_channels.dart @@ -96,28 +96,29 @@ class AllChannelsListEntry extends StatelessWidget { final Subscription? subscription = channel is Subscription ? channel : null; final hasContentAccess = store.selfHasContentAccess(channel); - return Padding( - padding: EdgeInsetsDirectional.only(start: 8, end: 4), - child: Row(spacing: 6, children: [ - Icon( - size: 20, - color: colorSwatchFor(context, subscription).iconOnPlainBackground, - iconDataForStream(channel)), - Expanded( - child: Text( - style: TextStyle( - color: designVariables.textMessage, - fontSize: 17, - height: 20 / 17, - ).merge(weightVariableTextStyle(context, wght: 600)), - channel.name)), - if (hasContentAccess) _SubscribeToggle(channel: channel), - ZulipIconButton( - icon: ZulipIcons.more_horizontal, - onPressed: () { - showChannelActionSheet(context, channelId: channel.streamId); - }), - ])); + return ConstrainedBox(constraints: const BoxConstraints(minHeight: 44), + child: Padding( + padding: EdgeInsetsDirectional.only(start: 8, end: 4), + child: Row(spacing: 6, children: [ + Icon( + size: 20, + color: colorSwatchFor(context, subscription).iconOnPlainBackground, + iconDataForStream(channel)), + Expanded( + child: Text( + style: TextStyle( + color: designVariables.textMessage, + fontSize: 17, + height: 20 / 17, + ).merge(weightVariableTextStyle(context, wght: 600)), + channel.name)), + if (hasContentAccess) _SubscribeToggle(channel: channel), + ZulipIconButton( + icon: ZulipIcons.more_horizontal, + onPressed: () { + showChannelActionSheet(context, channelId: channel.streamId); + }), + ]))); } } diff --git a/test/widgets/all_channels_test.dart b/test/widgets/all_channels_test.dart index b47546be40..801737e950 100644 --- a/test/widgets/all_channels_test.dart +++ b/test/widgets/all_channels_test.dart @@ -204,6 +204,9 @@ void main() { } check(findInRow(find.byIcon(ZulipIcons.more_horizontal))).findsOne(); + + final touchTargetSize = tester.getSize(findElement); + check(touchTargetSize.height).equals(44); } }); From 4b42f7a00c4066d4554a6f7ea0daa5f0a438075f Mon Sep 17 00:00:00 2001 From: chungwwei Date: Sat, 11 Oct 2025 04:52:51 -0400 Subject: [PATCH 2/3] all_channels: Remove three dot menu and add gesture controls Make the All Channels Page consistent with the Channel Page, as navigating to channel feed and opening the bottom sheet currently uses the three-dot menu icon, which differs from the gesture pattern used in the Channel Page. Fixes part of #1914 --- lib/widgets/all_channels.dart | 47 +++++++++++++++-------------- test/widgets/all_channels_test.dart | 23 +++++++++++--- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/lib/widgets/all_channels.dart b/lib/widgets/all_channels.dart index cda1969a87..1161681f39 100644 --- a/lib/widgets/all_channels.dart +++ b/lib/widgets/all_channels.dart @@ -5,11 +5,13 @@ import '../api/route/channels.dart'; import '../generated/l10n/zulip_localizations.dart'; import '../log.dart'; import '../model/channel.dart'; +import '../model/narrow.dart'; import 'action_sheet.dart'; import 'actions.dart'; import 'app_bar.dart'; import 'button.dart'; import 'icons.dart'; +import 'message_list.dart'; import 'page.dart'; import 'remote_settings.dart'; import 'store.dart'; @@ -96,29 +98,28 @@ class AllChannelsListEntry extends StatelessWidget { final Subscription? subscription = channel is Subscription ? channel : null; final hasContentAccess = store.selfHasContentAccess(channel); - return ConstrainedBox(constraints: const BoxConstraints(minHeight: 44), - child: Padding( - padding: EdgeInsetsDirectional.only(start: 8, end: 4), - child: Row(spacing: 6, children: [ - Icon( - size: 20, - color: colorSwatchFor(context, subscription).iconOnPlainBackground, - iconDataForStream(channel)), - Expanded( - child: Text( - style: TextStyle( - color: designVariables.textMessage, - fontSize: 17, - height: 20 / 17, - ).merge(weightVariableTextStyle(context, wght: 600)), - channel.name)), - if (hasContentAccess) _SubscribeToggle(channel: channel), - ZulipIconButton( - icon: ZulipIcons.more_horizontal, - onPressed: () { - showChannelActionSheet(context, channelId: channel.streamId); - }), - ]))); + return InkWell( + onTap: !hasContentAccess ? null : () => Navigator.push(context, + MessageListPage.buildRoute(context: context, + narrow: ChannelNarrow(channel.streamId))), + onLongPress: () => showChannelActionSheet(context, channelId: channel.streamId), + child: ConstrainedBox(constraints: const BoxConstraints(minHeight: 44), + child: Padding(padding: const EdgeInsetsDirectional.only(start: 8, end: 12), + child: Row(spacing: 6, children: [ + Icon( + size: 20, + color: colorSwatchFor(context, subscription).iconOnPlainBackground, + iconDataForStream(channel)), + Expanded( + child: Text( + style: TextStyle( + color: designVariables.textMessage, + fontSize: 17, + height: 20 / 17, + ).merge(weightVariableTextStyle(context, wght: 600)), + channel.name)), + if (hasContentAccess) _SubscribeToggle(channel: channel), + ])))); } } diff --git a/test/widgets/all_channels_test.dart b/test/widgets/all_channels_test.dart index 801737e950..f6e1092781 100644 --- a/test/widgets/all_channels_test.dart +++ b/test/widgets/all_channels_test.dart @@ -12,6 +12,7 @@ import 'package:zulip/widgets/app_bar.dart'; import 'package:zulip/widgets/button.dart'; import 'package:zulip/widgets/home.dart'; import 'package:zulip/widgets/icons.dart'; +import 'package:zulip/widgets/message_list.dart'; import 'package:zulip/widgets/page.dart'; import 'package:zulip/widgets/remote_settings.dart'; import 'package:zulip/widgets/theme.dart'; @@ -203,23 +204,37 @@ void main() { check(maybeToggle).isNull(); } - check(findInRow(find.byIcon(ZulipIcons.more_horizontal))).findsOne(); - final touchTargetSize = tester.getSize(findElement); check(touchTargetSize.height).equals(44); } }); - testWidgets('tapping three-dots button opens channel action sheet', (tester) async { + testWidgets('open channel action sheet on long press', (tester) async { await setupAllChannelsPage(tester, channels: [eg.stream()]); - await tester.tap(find.byIcon(ZulipIcons.more_horizontal)); + await tester.longPress(find.byType(AllChannelsListEntry)); await tester.pump(); await transitionDurationObserver.pumpPastTransition(tester); check(find.byType(BottomSheet)).findsOne(); }); + testWidgets('navigate to channel feed on tap', (tester) async { + final channel = eg.stream(name: 'some-channel'); + await setupAllChannelsPage(tester, channels: [channel]); + + connection.prepare(json: eg.newestGetMessagesResult( + foundOldest: true, messages: [eg.streamMessage(stream: channel)]).toJson()); + await tester.tap(find.byType(AllChannelsListEntry)); + await tester.pump(); + await transitionDurationObserver.pumpPastTransition(tester); + + check(find.descendant( + of: find.byType(MessageListPage), + matching: find.text('some-channel')), + ).findsOne(); + }); + testWidgets('use toggle switch to subscribe/unsubscribe', (tester) async { final channel = eg.stream(); await setupAllChannelsPage(tester, channels: [channel]); From 8942c912968af66a565066f8b9cefd5fa693551f Mon Sep 17 00:00:00 2001 From: chungwwei Date: Sun, 26 Oct 2025 00:40:44 -0400 Subject: [PATCH 3/3] all_channels: Restrict channel name to one line Previously, long name could span multiple lines when the system font size was large, causing the row height to become insconsistent with other items. Limiting the name to a single line ensures consistent row height, similar to how it's done on the Channel Page. Fixes #1914 --- lib/widgets/all_channels.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/widgets/all_channels.dart b/lib/widgets/all_channels.dart index 1161681f39..7d662bcc2d 100644 --- a/lib/widgets/all_channels.dart +++ b/lib/widgets/all_channels.dart @@ -112,6 +112,8 @@ class AllChannelsListEntry extends StatelessWidget { iconDataForStream(channel)), Expanded( child: Text( + maxLines: 1, + overflow: TextOverflow.ellipsis, style: TextStyle( color: designVariables.textMessage, fontSize: 17,