Skip to content

Commit 1bc6ec1

Browse files
committed
inbox: Add label for archived channels in headers
Fixes #800
1 parent 8a0c4da commit 1bc6ec1

13 files changed

+154
-17
lines changed

Diff for: assets/l10n/app_en.arb

+4
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,10 @@
363363
"@unknownChannelName": {
364364
"description": "Replacement name for channel when it cannot be found in the store."
365365
},
366+
"channelArchivedLabel": "(archived)",
367+
"@channelArchivedLabel": {
368+
"description": "Label shown next to an archived channel's name in headers."
369+
},
366370
"composeBoxTopicHintText": "Topic",
367371
"@composeBoxTopicHintText": {
368372
"description": "Hint text for topic input widget in compose box."

Diff for: lib/generated/l10n/zulip_localizations.dart

+6
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,12 @@ abstract class ZulipLocalizations {
585585
/// **'(unknown channel)'**
586586
String get unknownChannelName;
587587

588+
/// Label shown next to an archived channel's name in headers.
589+
///
590+
/// In en, this message translates to:
591+
/// **'(archived)'**
592+
String get channelArchivedLabel;
593+
588594
/// Hint text for topic input widget in compose box.
589595
///
590596
/// In en, this message translates to:

Diff for: lib/generated/l10n/zulip_localizations_ar.dart

+3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
286286
@override
287287
String get unknownChannelName => '(unknown channel)';
288288

289+
@override
290+
String get channelArchivedLabel => '(archived)';
291+
289292
@override
290293
String get composeBoxTopicHintText => 'Topic';
291294

Diff for: lib/generated/l10n/zulip_localizations_en.dart

+3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
286286
@override
287287
String get unknownChannelName => '(unknown channel)';
288288

289+
@override
290+
String get channelArchivedLabel => '(archived)';
291+
289292
@override
290293
String get composeBoxTopicHintText => 'Topic';
291294

Diff for: lib/generated/l10n/zulip_localizations_ja.dart

+3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
286286
@override
287287
String get unknownChannelName => '(unknown channel)';
288288

289+
@override
290+
String get channelArchivedLabel => '(archived)';
291+
289292
@override
290293
String get composeBoxTopicHintText => 'Topic';
291294

Diff for: lib/generated/l10n/zulip_localizations_nb.dart

+3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
286286
@override
287287
String get unknownChannelName => '(unknown channel)';
288288

289+
@override
290+
String get channelArchivedLabel => '(archived)';
291+
289292
@override
290293
String get composeBoxTopicHintText => 'Topic';
291294

Diff for: lib/generated/l10n/zulip_localizations_pl.dart

+3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
286286
@override
287287
String get unknownChannelName => '(nieznany kanał)';
288288

289+
@override
290+
String get channelArchivedLabel => '(archived)';
291+
289292
@override
290293
String get composeBoxTopicHintText => 'Wątek';
291294

Diff for: lib/generated/l10n/zulip_localizations_ru.dart

+3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
286286
@override
287287
String get unknownChannelName => '(unknown channel)';
288288

289+
@override
290+
String get channelArchivedLabel => '(archived)';
291+
289292
@override
290293
String get composeBoxTopicHintText => 'Тема';
291294

Diff for: lib/generated/l10n/zulip_localizations_sk.dart

+3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
286286
@override
287287
String get unknownChannelName => '(unknown channel)';
288288

289+
@override
290+
String get channelArchivedLabel => '(archived)';
291+
289292
@override
290293
String get composeBoxTopicHintText => 'Topic';
291294

Diff for: lib/widgets/inbox.dart

+28-8
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ abstract class _HeaderItem extends StatelessWidget {
222222
final _InboxPageState pageState;
223223
final int count;
224224
final bool hasMention;
225+
final bool isArchived;
225226

226227
/// A build context within the [_StreamSection] or [_AllDmsSection].
227228
///
@@ -236,6 +237,7 @@ abstract class _HeaderItem extends StatelessWidget {
236237
required this.count,
237238
required this.hasMention,
238239
required this.sectionContext,
240+
this.isArchived = false,
239241
});
240242

241243
String title(ZulipLocalizations zulipLocalizations);
@@ -284,16 +286,32 @@ abstract class _HeaderItem extends StatelessWidget {
284286
const SizedBox(width: 5),
285287
Expanded(child: Padding(
286288
padding: const EdgeInsets.symmetric(vertical: 4),
287-
child: Text(
288-
style: TextStyle(
289-
fontSize: 17,
290-
height: (20 / 17),
291-
// TODO(design) check if this is the right variable
292-
color: designVariables.labelMenuButton,
293-
).merge(weightVariableTextStyle(context, wght: 600)),
289+
child: RichText(
294290
maxLines: 1,
295291
overflow: TextOverflow.ellipsis,
296-
title(zulipLocalizations)))),
292+
text: TextSpan(
293+
children: [
294+
TextSpan(
295+
text: title(zulipLocalizations),
296+
style: TextStyle(
297+
fontSize: 17,
298+
height: 20 / 17,
299+
// TODO(design) check if this is the right variable
300+
color: designVariables.labelMenuButton,
301+
).merge(weightVariableTextStyle(context, wght: 600))),
302+
if (isArchived)
303+
// TODO(#1285): Avoid concatenating translated strings
304+
WidgetSpan(
305+
child: Padding(
306+
padding: EdgeInsetsDirectional.only(start: 4),
307+
child: Text(
308+
' ${zulipLocalizations.channelArchivedLabel}',
309+
style: TextStyle(
310+
fontSize: 17,
311+
height: 20 / 17,
312+
color: MessageListTheme.of(context).streamRecipientHeaderChevronRight,
313+
fontStyle: FontStyle.italic)))),
314+
])))),
297315
const SizedBox(width: 12),
298316
if (hasMention) const _IconMarker(icon: ZulipIcons.at_sign),
299317
Padding(padding: const EdgeInsetsDirectional.only(end: 16),
@@ -435,6 +453,7 @@ class _StreamHeaderItem extends _HeaderItem {
435453
required super.count,
436454
required super.hasMention,
437455
required super.sectionContext,
456+
required super.isArchived,
438457
});
439458

440459
@override String title(ZulipLocalizations zulipLocalizations) =>
@@ -481,6 +500,7 @@ class _StreamSection extends StatelessWidget {
481500
collapsed: collapsed,
482501
pageState: pageState,
483502
sectionContext: context,
503+
isArchived: subscription.isArchived,
484504
);
485505
return StickyHeaderItem(
486506
header: header,

Diff for: lib/widgets/message_list.dart

+20
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ class MessageListAppBarTitle extends StatelessWidget {
338338
ZulipStream? stream,
339339
}) {
340340
final zulipLocalizations = ZulipLocalizations.of(context);
341+
final messageListTheme = MessageListTheme.of(context);
341342
// A null [Icon.icon] makes a blank space.
342343
final icon = stream != null ? iconDataForStream(stream) : null;
343344
return Row(
@@ -351,6 +352,15 @@ class MessageListAppBarTitle extends StatelessWidget {
351352
const SizedBox(width: 4),
352353
Flexible(child: Text(
353354
stream?.name ?? zulipLocalizations.unknownChannelName)),
355+
if (stream?.isArchived ?? false)
356+
Padding(
357+
padding: EdgeInsetsDirectional.fromSTEB(4, 4, 0, 4),
358+
child: Text(
359+
' ${zulipLocalizations.channelArchivedLabel}',
360+
style: TextStyle(
361+
fontSize: 18,
362+
color: messageListTheme.streamRecipientHeaderChevronRight,
363+
fontStyle: FontStyle.italic))),
354364
]);
355365
}
356366

@@ -1104,6 +1114,16 @@ class StreamMessageRecipientHeader extends StatelessWidget {
11041114
style: recipientHeaderTextStyle(context),
11051115
overflow: TextOverflow.ellipsis),
11061116
),
1117+
if (stream?.isArchived ?? false)
1118+
Padding(
1119+
padding: const EdgeInsetsDirectional.fromSTEB(4, 4, 0, 4),
1120+
child: Text(
1121+
' ${zulipLocalizations.channelArchivedLabel}',
1122+
style: recipientHeaderTextStyle(context).copyWith(
1123+
color: messageListTheme.streamRecipientHeaderChevronRight,
1124+
fontStyle: FontStyle.italic),
1125+
overflow: TextOverflow.ellipsis,
1126+
maxLines: 1)),
11071127
Padding(
11081128
// Figma has 5px horizontal padding around an 8px wide icon.
11091129
// Icon is 16px wide here so horizontal padding is 1px.

Diff for: test/widgets/inbox_test.dart

+53-9
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,29 @@ void main() {
118118

119119
/// Find a row with the given label.
120120
Widget? findRowByLabel(WidgetTester tester, String label) {
121-
final rowLabel = tester.widgetList(
122-
find.text(label),
123-
).firstOrNull;
124-
if (rowLabel == null) {
125-
return null;
121+
final textFinder = find.text(label);
122+
if (textFinder.evaluate().isNotEmpty) {
123+
return tester.widget(
124+
find.ancestor(
125+
of: textFinder.first,
126+
matching: find.byType(Row))
127+
);
126128
}
127129

128-
return tester.widget(
129-
find.ancestor(
130-
of: find.byWidget(rowLabel),
131-
matching: find.byType(Row)));
130+
final richTextFinder = find.byWidgetPredicate((widget) =>
131+
widget is RichText &&
132+
widget.text.toPlainText().contains(label)
133+
);
134+
135+
if (richTextFinder.evaluate().isNotEmpty) {
136+
return tester.widget(
137+
find.ancestor(
138+
of: richTextFinder.first,
139+
matching: find.byType(Row))
140+
);
141+
}
142+
143+
return null;
132144
}
133145

134146
/// Find the all-DMs header element.
@@ -595,6 +607,38 @@ void main() {
595607
check(rectAfterTap).equals(rectBeforeTap);
596608
});
597609

610+
testWidgets('shows archived label for archived streams', (tester) async {
611+
final stream = eg.stream(streamId: 1, isArchived: true);
612+
final subscription = eg.subscription(stream);
613+
await setupPage(tester,
614+
streams: [stream],
615+
subscriptions: [subscription],
616+
unreadMessages: [eg.streamMessage(stream: stream)]);
617+
await tester.pumpAndSettle();
618+
619+
final headerRowFinder = findStreamHeaderRow(tester, stream.streamId);
620+
check(headerRowFinder).isNotNull();
621+
622+
final richTextFinder = find.descendant(
623+
of: find.byWidget(headerRowFinder!),
624+
matching: find.byWidgetPredicate((widget) =>
625+
widget is RichText &&
626+
widget.text.toPlainText().contains(stream.name)
627+
),
628+
);
629+
expect(richTextFinder, findsOneWidget);
630+
631+
final archivedLabelFinder = find.descendant(
632+
of: find.byWidget(headerRowFinder),
633+
matching: find.text(' (archived)')
634+
);
635+
expect(archivedLabelFinder, findsOneWidget);
636+
637+
// Check that the Text widget has italic style
638+
final archivedLabelText = tester.widget<Text>(archivedLabelFinder);
639+
expect(archivedLabelText.style?.fontStyle, FontStyle.italic);
640+
});
641+
598642
// TODO check it remains collapsed even if you scroll far away and back
599643

600644
// TODO check that it's always uncollapsed when it appears after being

Diff for: test/widgets/message_list_test.dart

+22
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,28 @@ void main() {
11011101
await tester.pump();
11021102
check(pushedRoutes).isEmpty();
11031103
});
1104+
1105+
testWidgets('shows archived label for archived streams', (tester) async {
1106+
final stream = eg.stream(streamId: 1, name: 'stream name', isArchived: true);
1107+
final message = eg.streamMessage(stream: stream, topic: 'topic');
1108+
1109+
await setupMessageListPage(tester,
1110+
narrow: const CombinedFeedNarrow(),
1111+
messages: [message],
1112+
streams: [stream],
1113+
subscriptions: [eg.subscription(stream)]);
1114+
await tester.pump();
1115+
1116+
check(findInMessageList('stream name')).length.equals(1);
1117+
check(findInMessageList(" (archived)")).length.equals(1);
1118+
1119+
final archivedLabelFinder = find.descendant(
1120+
of: find.byType(MessageList),
1121+
matching: find.text(" (archived)"),
1122+
);
1123+
final textWidget = tester.widget<Text>(archivedLabelFinder);
1124+
expect(textWidget.style?.fontStyle, FontStyle.italic);
1125+
});
11041126
});
11051127

11061128
group('DmRecipientHeader', () {

0 commit comments

Comments
 (0)