Skip to content

Commit 771f58c

Browse files
committed
topicList: Add topic list page for each channel
fixes: #1158
1 parent ec9aa35 commit 771f58c

20 files changed

+993
-42
lines changed

assets/icons/ZulipIcons.ttf

408 Bytes
Binary file not shown.

assets/icons/chevron_down.svg

+3
Loading

assets/icons/list.svg

+3
Loading

assets/l10n/app_en.arb

+16
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@
108108
"@actionSheetOptionUnresolveTopic": {
109109
"description": "Label for the 'Mark as unresolved' button on the topic action sheet."
110110
},
111+
"actionSheetOptionTopicList": "Topic list",
112+
"@actionSheetOptionTopicList": {
113+
"description": "Label for a button in the channel action sheet that opens the list of topics in the channel"
114+
},
111115
"errorResolveTopicFailedTitle": "Failed to mark topic as resolved",
112116
"@errorResolveTopicFailedTitle": {
113117
"description": "Error title when marking a topic as resolved failed."
@@ -710,6 +714,10 @@
710714
"@channelFeedButtonTooltip": {
711715
"description": "Tooltip for button to navigate to a given channel's feed"
712716
},
717+
"topicListButtonTooltip": "Topic list",
718+
"@topicListButtonTooltip": {
719+
"description": "Tooltip for button to navigate to topic list page."
720+
},
713721
"notifGroupDmConversationLabel": "{senderFullName} to you and {numOthers, plural, =1{1 other} other{{numOthers} others}}",
714722
"@notifGroupDmConversationLabel": {
715723
"description": "Label for a group DM conversation notification.",
@@ -868,6 +876,14 @@
868876
"@emojiPickerSearchEmoji": {
869877
"description": "Hint text for the emoji picker search text field."
870878
},
879+
"errorFetchingTopics": "Error fetching topics",
880+
"@errorFetchingTopics": {
881+
"description": "Error title when fetching the topics failed."
882+
},
883+
"noTopicsInChannel": "No topics in the channel",
884+
"@noTopicsInChannel": {
885+
"description": "Text to show when a channel has no topics."
886+
},
871887
"noEarlierMessages": "No earlier messages",
872888
"@noEarlierMessages": {
873889
"description": "Text to show at the start of a message list if there are no earlier messages."

lib/generated/l10n/zulip_localizations.dart

+24
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,12 @@ abstract class ZulipLocalizations {
267267
/// **'Mark as unresolved'**
268268
String get actionSheetOptionUnresolveTopic;
269269

270+
/// Label for a button in the channel action sheet that opens the list of topics in the channel
271+
///
272+
/// In en, this message translates to:
273+
/// **'Topic list'**
274+
String get actionSheetOptionTopicList;
275+
270276
/// Error title when marking a topic as resolved failed.
271277
///
272278
/// In en, this message translates to:
@@ -1047,6 +1053,12 @@ abstract class ZulipLocalizations {
10471053
/// **'Channel feed'**
10481054
String get channelFeedButtonTooltip;
10491055

1056+
/// Tooltip for button to navigate to topic list page.
1057+
///
1058+
/// In en, this message translates to:
1059+
/// **'Topic list'**
1060+
String get topicListButtonTooltip;
1061+
10501062
/// Label for a group DM conversation notification.
10511063
///
10521064
/// In en, this message translates to:
@@ -1263,6 +1275,18 @@ abstract class ZulipLocalizations {
12631275
/// **'Search emoji'**
12641276
String get emojiPickerSearchEmoji;
12651277

1278+
/// Error title when fetching the topics failed.
1279+
///
1280+
/// In en, this message translates to:
1281+
/// **'Error fetching topics'**
1282+
String get errorFetchingTopics;
1283+
1284+
/// Text to show when a channel has no topics.
1285+
///
1286+
/// In en, this message translates to:
1287+
/// **'No topics in the channel'**
1288+
String get noTopicsInChannel;
1289+
12661290
/// Text to show at the start of a message list if there are no earlier messages.
12671291
///
12681292
/// In en, this message translates to:

lib/generated/l10n/zulip_localizations_ar.dart

+12
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
9191
@override
9292
String get actionSheetOptionUnresolveTopic => 'Mark as unresolved';
9393

94+
@override
95+
String get actionSheetOptionTopicList => 'Topic list';
96+
9497
@override
9598
String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved';
9699

@@ -553,6 +556,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
553556
@override
554557
String get channelFeedButtonTooltip => 'Channel feed';
555558

559+
@override
560+
String get topicListButtonTooltip => 'Topic list';
561+
556562
@override
557563
String notifGroupDmConversationLabel(String senderFullName, int numOthers) {
558564
String _temp0 = intl.Intl.pluralLogic(
@@ -675,6 +681,12 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
675681
@override
676682
String get emojiPickerSearchEmoji => 'Search emoji';
677683

684+
@override
685+
String get errorFetchingTopics => 'Error fetching topics';
686+
687+
@override
688+
String get noTopicsInChannel => 'No topics in the channel';
689+
678690
@override
679691
String get noEarlierMessages => 'No earlier messages';
680692

lib/generated/l10n/zulip_localizations_en.dart

+12
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
9191
@override
9292
String get actionSheetOptionUnresolveTopic => 'Mark as unresolved';
9393

94+
@override
95+
String get actionSheetOptionTopicList => 'Topic list';
96+
9497
@override
9598
String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved';
9699

@@ -553,6 +556,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
553556
@override
554557
String get channelFeedButtonTooltip => 'Channel feed';
555558

559+
@override
560+
String get topicListButtonTooltip => 'Topic list';
561+
556562
@override
557563
String notifGroupDmConversationLabel(String senderFullName, int numOthers) {
558564
String _temp0 = intl.Intl.pluralLogic(
@@ -675,6 +681,12 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
675681
@override
676682
String get emojiPickerSearchEmoji => 'Search emoji';
677683

684+
@override
685+
String get errorFetchingTopics => 'Error fetching topics';
686+
687+
@override
688+
String get noTopicsInChannel => 'No topics in the channel';
689+
678690
@override
679691
String get noEarlierMessages => 'No earlier messages';
680692

lib/generated/l10n/zulip_localizations_ja.dart

+12
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
9191
@override
9292
String get actionSheetOptionUnresolveTopic => 'Mark as unresolved';
9393

94+
@override
95+
String get actionSheetOptionTopicList => 'Topic list';
96+
9497
@override
9598
String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved';
9699

@@ -553,6 +556,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
553556
@override
554557
String get channelFeedButtonTooltip => 'Channel feed';
555558

559+
@override
560+
String get topicListButtonTooltip => 'Topic list';
561+
556562
@override
557563
String notifGroupDmConversationLabel(String senderFullName, int numOthers) {
558564
String _temp0 = intl.Intl.pluralLogic(
@@ -675,6 +681,12 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
675681
@override
676682
String get emojiPickerSearchEmoji => 'Search emoji';
677683

684+
@override
685+
String get errorFetchingTopics => 'Error fetching topics';
686+
687+
@override
688+
String get noTopicsInChannel => 'No topics in the channel';
689+
678690
@override
679691
String get noEarlierMessages => 'No earlier messages';
680692

lib/generated/l10n/zulip_localizations_nb.dart

+12
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
9191
@override
9292
String get actionSheetOptionUnresolveTopic => 'Mark as unresolved';
9393

94+
@override
95+
String get actionSheetOptionTopicList => 'Topic list';
96+
9497
@override
9598
String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved';
9699

@@ -553,6 +556,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
553556
@override
554557
String get channelFeedButtonTooltip => 'Channel feed';
555558

559+
@override
560+
String get topicListButtonTooltip => 'Topic list';
561+
556562
@override
557563
String notifGroupDmConversationLabel(String senderFullName, int numOthers) {
558564
String _temp0 = intl.Intl.pluralLogic(
@@ -675,6 +681,12 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
675681
@override
676682
String get emojiPickerSearchEmoji => 'Search emoji';
677683

684+
@override
685+
String get errorFetchingTopics => 'Error fetching topics';
686+
687+
@override
688+
String get noTopicsInChannel => 'No topics in the channel';
689+
678690
@override
679691
String get noEarlierMessages => 'No earlier messages';
680692

lib/generated/l10n/zulip_localizations_pl.dart

+12
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
9191
@override
9292
String get actionSheetOptionUnresolveTopic => 'Oznacz brak rozwiązania';
9393

94+
@override
95+
String get actionSheetOptionTopicList => 'Topic list';
96+
9497
@override
9598
String get errorResolveTopicFailedTitle => 'Nie udało się oznaczyć jako rozwiązany';
9699

@@ -553,6 +556,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
553556
@override
554557
String get channelFeedButtonTooltip => 'Strumień kanału';
555558

559+
@override
560+
String get topicListButtonTooltip => 'Topic list';
561+
556562
@override
557563
String notifGroupDmConversationLabel(String senderFullName, int numOthers) {
558564
String _temp0 = intl.Intl.pluralLogic(
@@ -675,6 +681,12 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
675681
@override
676682
String get emojiPickerSearchEmoji => 'Szukaj emoji';
677683

684+
@override
685+
String get errorFetchingTopics => 'Error fetching topics';
686+
687+
@override
688+
String get noTopicsInChannel => 'No topics in the channel';
689+
678690
@override
679691
String get noEarlierMessages => 'Brak historii';
680692

lib/generated/l10n/zulip_localizations_ru.dart

+12
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
9191
@override
9292
String get actionSheetOptionUnresolveTopic => 'Mark as unresolved';
9393

94+
@override
95+
String get actionSheetOptionTopicList => 'Topic list';
96+
9497
@override
9598
String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved';
9699

@@ -553,6 +556,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
553556
@override
554557
String get channelFeedButtonTooltip => 'Лента канала';
555558

559+
@override
560+
String get topicListButtonTooltip => 'Topic list';
561+
556562
@override
557563
String notifGroupDmConversationLabel(String senderFullName, int numOthers) {
558564
String _temp0 = intl.Intl.pluralLogic(
@@ -675,6 +681,12 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
675681
@override
676682
String get emojiPickerSearchEmoji => 'Поиск эмодзи';
677683

684+
@override
685+
String get errorFetchingTopics => 'Error fetching topics';
686+
687+
@override
688+
String get noTopicsInChannel => 'No topics in the channel';
689+
678690
@override
679691
String get noEarlierMessages => 'No earlier messages';
680692

lib/generated/l10n/zulip_localizations_sk.dart

+12
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
9191
@override
9292
String get actionSheetOptionUnresolveTopic => 'Mark as unresolved';
9393

94+
@override
95+
String get actionSheetOptionTopicList => 'Topic list';
96+
9497
@override
9598
String get errorResolveTopicFailedTitle => 'Failed to mark topic as resolved';
9699

@@ -553,6 +556,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
553556
@override
554557
String get channelFeedButtonTooltip => 'Channel feed';
555558

559+
@override
560+
String get topicListButtonTooltip => 'Topic list';
561+
556562
@override
557563
String notifGroupDmConversationLabel(String senderFullName, int numOthers) {
558564
String _temp0 = intl.Intl.pluralLogic(
@@ -675,6 +681,12 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
675681
@override
676682
String get emojiPickerSearchEmoji => 'Hľadať emotikon';
677683

684+
@override
685+
String get errorFetchingTopics => 'Error fetching topics';
686+
687+
@override
688+
String get noTopicsInChannel => 'No topics in the channel';
689+
678690
@override
679691
String get noEarlierMessages => 'No earlier messages';
680692

lib/widgets/action_sheet.dart

+33-9
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, {
@@ -175,23 +176,46 @@ void showChannelActionSheet(BuildContext context, {
175176
final store = PerAccountStoreWidget.of(pageContext);
176177

177178
final optionButtons = <ActionSheetMenuItemButton>[];
179+
180+
optionButtons.add(
181+
TopicListButton(pageContext: pageContext, channelId: channelId));
182+
178183
final unreadCount = store.unreads.countInChannelNarrow(channelId);
179184
if (unreadCount > 0) {
180185
optionButtons.add(
181186
MarkChannelAsReadButton(pageContext: pageContext, channelId: channelId));
182187
}
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-
}
188+
192189
_showActionSheet(pageContext, optionButtons: optionButtons);
193190
}
194191

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

0 commit comments

Comments
 (0)