Skip to content

Commit f655e45

Browse files
lakshya1goelPIG208
andcommitted
topics: Add TopicListButton to channel action sheet
The icon was taken from CZO discussion: https://chat.zulip.org/#narrow/channel/530-mobile-design/topic/Topic.20list.20in.20channel/near/2140324 Fixes: #1158 Co-authored-by: Zixuan James Li <[email protected]>
1 parent 5b8648a commit f655e45

15 files changed

+87
-13
lines changed

assets/icons/ZulipIcons.ttf

280 Bytes
Binary file not shown.

assets/icons/topics.svg

+3
Loading

assets/l10n/app_en.arb

+4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@
8484
"@actionSheetOptionMarkChannelAsRead": {
8585
"description": "Label for marking a channel as read."
8686
},
87+
"actionSheetOptionTopicList": "Topic list",
88+
"@actionSheetOptionTopicList": {
89+
"description": "Label for navigating to a channel's topic-list page."
90+
},
8791
"actionSheetOptionMuteTopic": "Mute topic",
8892
"@actionSheetOptionMuteTopic": {
8993
"description": "Label for muting a topic on action sheet."

lib/generated/l10n/zulip_localizations.dart

+6
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,12 @@ abstract class ZulipLocalizations {
236236
/// **'Mark channel as read'**
237237
String get actionSheetOptionMarkChannelAsRead;
238238

239+
/// Label for navigating to a channel's topic-list page.
240+
///
241+
/// In en, this message translates to:
242+
/// **'Topic list'**
243+
String get actionSheetOptionTopicList;
244+
239245
/// Label for muting a topic on action sheet.
240246
///
241247
/// In en, this message translates to:

lib/generated/l10n/zulip_localizations_ar.dart

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
7676
@override
7777
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
7878

79+
@override
80+
String get actionSheetOptionTopicList => 'Topic list';
81+
7982
@override
8083
String get actionSheetOptionMuteTopic => 'Mute topic';
8184

lib/generated/l10n/zulip_localizations_en.dart

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
7676
@override
7777
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
7878

79+
@override
80+
String get actionSheetOptionTopicList => 'Topic list';
81+
7982
@override
8083
String get actionSheetOptionMuteTopic => 'Mute topic';
8184

lib/generated/l10n/zulip_localizations_ja.dart

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
7676
@override
7777
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
7878

79+
@override
80+
String get actionSheetOptionTopicList => 'Topic list';
81+
7982
@override
8083
String get actionSheetOptionMuteTopic => 'Mute topic';
8184

lib/generated/l10n/zulip_localizations_nb.dart

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
7676
@override
7777
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
7878

79+
@override
80+
String get actionSheetOptionTopicList => 'Topic list';
81+
7982
@override
8083
String get actionSheetOptionMuteTopic => 'Mute topic';
8184

lib/generated/l10n/zulip_localizations_pl.dart

+3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
7878
String get actionSheetOptionMarkChannelAsRead =>
7979
'Oznacz kanał jako przeczytany';
8080

81+
@override
82+
String get actionSheetOptionTopicList => 'Topic list';
83+
8184
@override
8285
String get actionSheetOptionMuteTopic => 'Wycisz wątek';
8386

lib/generated/l10n/zulip_localizations_ru.dart

+3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
7878
String get actionSheetOptionMarkChannelAsRead =>
7979
'Отметить канал как прочитанный';
8080

81+
@override
82+
String get actionSheetOptionTopicList => 'Topic list';
83+
8184
@override
8285
String get actionSheetOptionMuteTopic => 'Отключить тему';
8386

lib/generated/l10n/zulip_localizations_sk.dart

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
7676
@override
7777
String get actionSheetOptionMarkChannelAsRead => 'Mark channel as read';
7878

79+
@override
80+
String get actionSheetOptionTopicList => 'Topic list';
81+
7982
@override
8083
String get actionSheetOptionMuteTopic => 'Stlmiť tému';
8184

lib/generated/l10n/zulip_localizations_uk.dart

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ class ZulipLocalizationsUk extends ZulipLocalizations {
7979
String get actionSheetOptionMarkChannelAsRead =>
8080
'Позначити канал як прочитаний';
8181

82+
@override
83+
String get actionSheetOptionTopicList => 'Topic list';
84+
8285
@override
8386
String get actionSheetOptionMuteTopic => 'Заглушити тему';
8487

lib/widgets/action_sheet.dart

+30-10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import 'page.dart';
2828
import 'store.dart';
2929
import 'text.dart';
3030
import 'theme.dart';
31+
import 'topic_list.dart';
3132

3233
void _showActionSheet(
3334
BuildContext context, {
@@ -174,24 +175,43 @@ void showChannelActionSheet(BuildContext context, {
174175
final pageContext = PageRoot.contextOf(context);
175176
final store = PerAccountStoreWidget.of(pageContext);
176177

177-
final optionButtons = <ActionSheetMenuItemButton>[];
178+
final optionButtons = <ActionSheetMenuItemButton>[
179+
TopicListButton(pageContext: pageContext, channelId: channelId),
180+
];
181+
178182
final unreadCount = store.unreads.countInChannelNarrow(channelId);
179183
if (unreadCount > 0) {
180184
optionButtons.add(
181185
MarkChannelAsReadButton(pageContext: pageContext, channelId: channelId));
182186
}
183-
if (optionButtons.isEmpty) {
184-
// TODO(a11y): This case makes a no-op gesture handler; as a consequence,
185-
// we're presenting some UI (to people who use screen-reader software) as
186-
// though it offers a gesture interaction that it doesn't meaningfully
187-
// offer, which is confusing. The solution here is probably to remove this
188-
// is-empty case by having at least one button that's always present,
189-
// such as "copy link to channel".
190-
return;
191-
}
187+
192188
_showActionSheet(pageContext, optionButtons: optionButtons);
193189
}
194190

191+
class TopicListButton extends ActionSheetMenuItemButton {
192+
const TopicListButton({
193+
super.key,
194+
required this.channelId,
195+
required super.pageContext,
196+
});
197+
198+
final int channelId;
199+
200+
@override
201+
IconData get icon => ZulipIcons.topics;
202+
203+
@override
204+
String label(ZulipLocalizations zulipLocalizations) {
205+
return zulipLocalizations.actionSheetOptionTopicList;
206+
}
207+
208+
@override
209+
void onPressed() {
210+
Navigator.push(pageContext,
211+
TopicListPage.buildRoute(context: pageContext, streamId: channelId));
212+
}
213+
}
214+
195215
class MarkChannelAsReadButton extends ActionSheetMenuItemButton {
196216
const MarkChannelAsReadButton({
197217
super.key,

lib/widgets/icons.dart

+5-2
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,14 @@ abstract final class ZulipIcons {
147147
/// The Zulip custom icon "topic".
148148
static const IconData topic = IconData(0xf129, fontFamily: "Zulip Icons");
149149

150+
/// The Zulip custom icon "topics".
151+
static const IconData topics = IconData(0xf12a, fontFamily: "Zulip Icons");
152+
150153
/// The Zulip custom icon "unmute".
151-
static const IconData unmute = IconData(0xf12a, fontFamily: "Zulip Icons");
154+
static const IconData unmute = IconData(0xf12b, fontFamily: "Zulip Icons");
152155

153156
/// The Zulip custom icon "user".
154-
static const IconData user = IconData(0xf12b, fontFamily: "Zulip Icons");
157+
static const IconData user = IconData(0xf12c, fontFamily: "Zulip Icons");
155158

156159
// END GENERATED ICON DATA
157160
}

test/widgets/action_sheet_test.dart

+15-1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ void main() {
201201
void checkButtons() {
202202
check(actionSheetFinder).findsOne();
203203
checkButton('Mark channel as read');
204+
checkButton('Topic list');
204205
}
205206

206207
testWidgets('show from inbox', (tester) async {
@@ -218,7 +219,7 @@ void main() {
218219
testWidgets('show with no unread messages', (tester) async {
219220
await prepare(hasUnreadMessages: false);
220221
await showFromSubscriptionList(tester);
221-
check(actionSheetFinder).findsNothing();
222+
check(findButtonForLabel('Mark channel as read')).findsNothing();
222223
});
223224

224225
testWidgets('show from app bar in channel narrow', (tester) async {
@@ -242,6 +243,19 @@ void main() {
242243
});
243244
});
244245

246+
testWidgets('TopicListButton', (tester) async {
247+
await prepare();
248+
await showFromAppBar(tester,
249+
narrow: ChannelNarrow(someChannel.streamId));
250+
251+
connection.prepare(json: GetStreamTopicsResult(topics: [
252+
eg.getStreamTopicsEntry(name: 'some topic foo'),
253+
]).toJson());
254+
await tester.tap(findButtonForLabel('Topic list'));
255+
await tester.pumpAndSettle();
256+
check(find.text('some topic foo')).findsOne();
257+
});
258+
245259
group('MarkChannelAsReadButton', () {
246260
void checkRequest(int channelId) {
247261
check(connection.takeRequests()).single.isA<http.Request>()

0 commit comments

Comments
 (0)