Skip to content

Commit 5b8648a

Browse files
committed
topics: Add topic list page
The topic-list page app bar should match the Figma design except for its height. That part needs to be coordinated with other pages. Also on the topic-list page app bar, the icon "chveron_down.svg" (originally "chveron-down-16.svg") comes from: https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=6820-36184&m=dev and not the "Icons" page, since the "chveron-down" there appears to be different from the one on the topic list page design. We also leave out the new topic button and topic filtering. Those are out-of-scope for #1158. --- On the message-list page, "TOPICS" is not aligned to the middle part of the app bar, that's because we haven't got to #1039 yet. --- The topic-list implementation is quite similar to parts of inbox page and message-list page. Therefore, we structure the code to make them look similar to compare for changes side-by-side to help with reviewing what has changed. Figma design: https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=6819-35869&m=dev
1 parent 1f45124 commit 5b8648a

17 files changed

+808
-41
lines changed

assets/icons/ZulipIcons.ttf

124 Bytes
Binary file not shown.

assets/icons/chevron_down.svg

+5
Loading

assets/l10n/app_en.arb

+4
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,10 @@
706706
"@mainMenuMyProfile": {
707707
"description": "Label for main-menu button leading to the user's own profile."
708708
},
709+
"topicsButtonLabel": "TOPICS",
710+
"@topicsButtonLabel": {
711+
"description": "Label for message list button leading to topic-list page. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)"
712+
},
709713
"channelFeedButtonTooltip": "Channel feed",
710714
"@channelFeedButtonTooltip": {
711715
"description": "Tooltip for button to navigate to a given channel's feed"

lib/generated/l10n/zulip_localizations.dart

+6
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,12 @@ abstract class ZulipLocalizations {
10581058
/// **'My profile'**
10591059
String get mainMenuMyProfile;
10601060

1061+
/// Label for message list button leading to topic-list page. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)
1062+
///
1063+
/// In en, this message translates to:
1064+
/// **'TOPICS'**
1065+
String get topicsButtonLabel;
1066+
10611067
/// Tooltip for button to navigate to a given channel's feed
10621068
///
10631069
/// In en, this message translates to:

lib/generated/l10n/zulip_localizations_ar.dart

+3
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
579579
@override
580580
String get mainMenuMyProfile => 'My profile';
581581

582+
@override
583+
String get topicsButtonLabel => 'TOPICS';
584+
582585
@override
583586
String get channelFeedButtonTooltip => 'Channel feed';
584587

lib/generated/l10n/zulip_localizations_en.dart

+3
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
579579
@override
580580
String get mainMenuMyProfile => 'My profile';
581581

582+
@override
583+
String get topicsButtonLabel => 'TOPICS';
584+
582585
@override
583586
String get channelFeedButtonTooltip => 'Channel feed';
584587

lib/generated/l10n/zulip_localizations_ja.dart

+3
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
579579
@override
580580
String get mainMenuMyProfile => 'My profile';
581581

582+
@override
583+
String get topicsButtonLabel => 'TOPICS';
584+
582585
@override
583586
String get channelFeedButtonTooltip => 'Channel feed';
584587

lib/generated/l10n/zulip_localizations_nb.dart

+3
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
579579
@override
580580
String get mainMenuMyProfile => 'My profile';
581581

582+
@override
583+
String get topicsButtonLabel => 'TOPICS';
584+
582585
@override
583586
String get channelFeedButtonTooltip => 'Channel feed';
584587

lib/generated/l10n/zulip_localizations_pl.dart

+3
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
588588
@override
589589
String get mainMenuMyProfile => 'Mój profil';
590590

591+
@override
592+
String get topicsButtonLabel => 'TOPICS';
593+
591594
@override
592595
String get channelFeedButtonTooltip => 'Strumień kanału';
593596

lib/generated/l10n/zulip_localizations_ru.dart

+3
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
592592
@override
593593
String get mainMenuMyProfile => 'Мой профиль';
594594

595+
@override
596+
String get topicsButtonLabel => 'TOPICS';
597+
595598
@override
596599
String get channelFeedButtonTooltip => 'Лента канала';
597600

lib/generated/l10n/zulip_localizations_sk.dart

+3
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
581581
@override
582582
String get mainMenuMyProfile => 'Môj profil';
583583

584+
@override
585+
String get topicsButtonLabel => 'TOPICS';
586+
584587
@override
585588
String get channelFeedButtonTooltip => 'Channel feed';
586589

lib/generated/l10n/zulip_localizations_uk.dart

+3
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,9 @@ class ZulipLocalizationsUk extends ZulipLocalizations {
591591
@override
592592
String get mainMenuMyProfile => 'Мій профіль';
593593

594+
@override
595+
String get topicsButtonLabel => 'TOPICS';
596+
594597
@override
595598
String get channelFeedButtonTooltip => 'Стрічка каналу';
596599

lib/widgets/icons.dart

+36-33
Original file line numberDiff line numberDiff line change
@@ -51,104 +51,107 @@ abstract final class ZulipIcons {
5151
/// The Zulip custom icon "check_remove".
5252
static const IconData check_remove = IconData(0xf109, fontFamily: "Zulip Icons");
5353

54+
/// The Zulip custom icon "chevron_down".
55+
static const IconData chevron_down = IconData(0xf10a, fontFamily: "Zulip Icons");
56+
5457
/// The Zulip custom icon "chevron_right".
55-
static const IconData chevron_right = IconData(0xf10a, fontFamily: "Zulip Icons");
58+
static const IconData chevron_right = IconData(0xf10b, fontFamily: "Zulip Icons");
5659

5760
/// The Zulip custom icon "clock".
58-
static const IconData clock = IconData(0xf10b, fontFamily: "Zulip Icons");
61+
static const IconData clock = IconData(0xf10c, fontFamily: "Zulip Icons");
5962

6063
/// The Zulip custom icon "contacts".
61-
static const IconData contacts = IconData(0xf10c, fontFamily: "Zulip Icons");
64+
static const IconData contacts = IconData(0xf10d, fontFamily: "Zulip Icons");
6265

6366
/// The Zulip custom icon "copy".
64-
static const IconData copy = IconData(0xf10d, fontFamily: "Zulip Icons");
67+
static const IconData copy = IconData(0xf10e, fontFamily: "Zulip Icons");
6568

6669
/// The Zulip custom icon "edit".
67-
static const IconData edit = IconData(0xf10e, fontFamily: "Zulip Icons");
70+
static const IconData edit = IconData(0xf10f, fontFamily: "Zulip Icons");
6871

6972
/// The Zulip custom icon "follow".
70-
static const IconData follow = IconData(0xf10f, fontFamily: "Zulip Icons");
73+
static const IconData follow = IconData(0xf110, fontFamily: "Zulip Icons");
7174

7275
/// The Zulip custom icon "format_quote".
73-
static const IconData format_quote = IconData(0xf110, fontFamily: "Zulip Icons");
76+
static const IconData format_quote = IconData(0xf111, fontFamily: "Zulip Icons");
7477

7578
/// The Zulip custom icon "globe".
76-
static const IconData globe = IconData(0xf111, fontFamily: "Zulip Icons");
79+
static const IconData globe = IconData(0xf112, fontFamily: "Zulip Icons");
7780

7881
/// The Zulip custom icon "group_dm".
79-
static const IconData group_dm = IconData(0xf112, fontFamily: "Zulip Icons");
82+
static const IconData group_dm = IconData(0xf113, fontFamily: "Zulip Icons");
8083

8184
/// The Zulip custom icon "hash_italic".
82-
static const IconData hash_italic = IconData(0xf113, fontFamily: "Zulip Icons");
85+
static const IconData hash_italic = IconData(0xf114, fontFamily: "Zulip Icons");
8386

8487
/// The Zulip custom icon "hash_sign".
85-
static const IconData hash_sign = IconData(0xf114, fontFamily: "Zulip Icons");
88+
static const IconData hash_sign = IconData(0xf115, fontFamily: "Zulip Icons");
8689

8790
/// The Zulip custom icon "image".
88-
static const IconData image = IconData(0xf115, fontFamily: "Zulip Icons");
91+
static const IconData image = IconData(0xf116, fontFamily: "Zulip Icons");
8992

9093
/// The Zulip custom icon "inbox".
91-
static const IconData inbox = IconData(0xf116, fontFamily: "Zulip Icons");
94+
static const IconData inbox = IconData(0xf117, fontFamily: "Zulip Icons");
9295

9396
/// The Zulip custom icon "info".
94-
static const IconData info = IconData(0xf117, fontFamily: "Zulip Icons");
97+
static const IconData info = IconData(0xf118, fontFamily: "Zulip Icons");
9598

9699
/// The Zulip custom icon "inherit".
97-
static const IconData inherit = IconData(0xf118, fontFamily: "Zulip Icons");
100+
static const IconData inherit = IconData(0xf119, fontFamily: "Zulip Icons");
98101

99102
/// The Zulip custom icon "language".
100-
static const IconData language = IconData(0xf119, fontFamily: "Zulip Icons");
103+
static const IconData language = IconData(0xf11a, fontFamily: "Zulip Icons");
101104

102105
/// The Zulip custom icon "lock".
103-
static const IconData lock = IconData(0xf11a, fontFamily: "Zulip Icons");
106+
static const IconData lock = IconData(0xf11b, fontFamily: "Zulip Icons");
104107

105108
/// The Zulip custom icon "menu".
106-
static const IconData menu = IconData(0xf11b, fontFamily: "Zulip Icons");
109+
static const IconData menu = IconData(0xf11c, fontFamily: "Zulip Icons");
107110

108111
/// The Zulip custom icon "message_checked".
109-
static const IconData message_checked = IconData(0xf11c, fontFamily: "Zulip Icons");
112+
static const IconData message_checked = IconData(0xf11d, fontFamily: "Zulip Icons");
110113

111114
/// The Zulip custom icon "message_feed".
112-
static const IconData message_feed = IconData(0xf11d, fontFamily: "Zulip Icons");
115+
static const IconData message_feed = IconData(0xf11e, fontFamily: "Zulip Icons");
113116

114117
/// The Zulip custom icon "mute".
115-
static const IconData mute = IconData(0xf11e, fontFamily: "Zulip Icons");
118+
static const IconData mute = IconData(0xf11f, fontFamily: "Zulip Icons");
116119

117120
/// The Zulip custom icon "read_receipts".
118-
static const IconData read_receipts = IconData(0xf11f, fontFamily: "Zulip Icons");
121+
static const IconData read_receipts = IconData(0xf120, fontFamily: "Zulip Icons");
119122

120123
/// The Zulip custom icon "send".
121-
static const IconData send = IconData(0xf120, fontFamily: "Zulip Icons");
124+
static const IconData send = IconData(0xf121, fontFamily: "Zulip Icons");
122125

123126
/// The Zulip custom icon "settings".
124-
static const IconData settings = IconData(0xf121, fontFamily: "Zulip Icons");
127+
static const IconData settings = IconData(0xf122, fontFamily: "Zulip Icons");
125128

126129
/// The Zulip custom icon "share".
127-
static const IconData share = IconData(0xf122, fontFamily: "Zulip Icons");
130+
static const IconData share = IconData(0xf123, fontFamily: "Zulip Icons");
128131

129132
/// The Zulip custom icon "share_ios".
130-
static const IconData share_ios = IconData(0xf123, fontFamily: "Zulip Icons");
133+
static const IconData share_ios = IconData(0xf124, fontFamily: "Zulip Icons");
131134

132135
/// The Zulip custom icon "smile".
133-
static const IconData smile = IconData(0xf124, fontFamily: "Zulip Icons");
136+
static const IconData smile = IconData(0xf125, fontFamily: "Zulip Icons");
134137

135138
/// The Zulip custom icon "star".
136-
static const IconData star = IconData(0xf125, fontFamily: "Zulip Icons");
139+
static const IconData star = IconData(0xf126, fontFamily: "Zulip Icons");
137140

138141
/// The Zulip custom icon "star_filled".
139-
static const IconData star_filled = IconData(0xf126, fontFamily: "Zulip Icons");
142+
static const IconData star_filled = IconData(0xf127, fontFamily: "Zulip Icons");
140143

141144
/// The Zulip custom icon "three_person".
142-
static const IconData three_person = IconData(0xf127, fontFamily: "Zulip Icons");
145+
static const IconData three_person = IconData(0xf128, fontFamily: "Zulip Icons");
143146

144147
/// The Zulip custom icon "topic".
145-
static const IconData topic = IconData(0xf128, fontFamily: "Zulip Icons");
148+
static const IconData topic = IconData(0xf129, fontFamily: "Zulip Icons");
146149

147150
/// The Zulip custom icon "unmute".
148-
static const IconData unmute = IconData(0xf129, fontFamily: "Zulip Icons");
151+
static const IconData unmute = IconData(0xf12a, fontFamily: "Zulip Icons");
149152

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

153156
// END GENERATED ICON DATA
154157
}

lib/widgets/message_list.dart

+35-8
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import 'sticky_header.dart';
2424
import 'store.dart';
2525
import 'text.dart';
2626
import 'theme.dart';
27+
import 'topic_list.dart';
2728

2829
/// Message-list styles that differ between light and dark themes.
2930
class MessageListTheme extends ThemeExtension<MessageListTheme> {
@@ -220,14 +221,40 @@ class _MessageListPageState extends State<MessageListPage> implements MessageLis
220221
removeAppBarBottomBorder = true;
221222
}
222223

223-
List<Widget>? actions;
224-
if (narrow case TopicNarrow(:final streamId)) {
225-
(actions ??= []).add(IconButton(
226-
icon: const Icon(ZulipIcons.message_feed),
227-
tooltip: zulipLocalizations.channelFeedButtonTooltip,
228-
onPressed: () => Navigator.push(context,
229-
MessageListPage.buildRoute(context: context,
230-
narrow: ChannelNarrow(streamId)))));
224+
List<Widget> actions = [];
225+
switch (narrow) {
226+
case CombinedFeedNarrow():
227+
case MentionsNarrow():
228+
case StarredMessagesNarrow():
229+
case DmNarrow():
230+
break;
231+
case ChannelNarrow(:final streamId):
232+
final designVariables = DesignVariables.of(context);
233+
final zulipLocalizations = ZulipLocalizations.of(context);
234+
actions.add(GestureDetector(
235+
onTap: () {
236+
Navigator.of(context).push(TopicListPage.buildRoute(
237+
context: context, streamId: streamId));
238+
},
239+
behavior: HitTestBehavior.opaque,
240+
child: Padding(
241+
padding: EdgeInsetsDirectional.fromSTEB(4, 8, 12, 8),
242+
child: Center(child: Text(zulipLocalizations.topicsButtonLabel,
243+
style: TextStyle(
244+
color: designVariables.icon,
245+
fontSize: 18,
246+
height: 19 / 18,
247+
// This is equivalent to css `all-small-caps`, see:
248+
// https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-caps#all-small-caps
249+
fontFeatures: const [FontFeature.enable('c2sc'), FontFeature.enable('smcp')],
250+
).merge(weightVariableTextStyle(context, wght: 600)))))));
251+
case TopicNarrow(:final streamId):
252+
actions.add(IconButton(
253+
icon: const Icon(ZulipIcons.message_feed),
254+
tooltip: zulipLocalizations.channelFeedButtonTooltip,
255+
onPressed: () => Navigator.push(context,
256+
MessageListPage.buildRoute(context: context,
257+
narrow: ChannelNarrow(streamId)))));
231258
}
232259

233260
// Insert a PageRoot here, to provide a context that can be used for

0 commit comments

Comments
 (0)