Skip to content

Commit f2cd833

Browse files
committed
content: Follow user_settings.twenty_four_hour_time in global times
Fixes #1015.
1 parent 1c6bd42 commit f2cd833

File tree

2 files changed

+68
-9
lines changed

2 files changed

+68
-9
lines changed

lib/widgets/content.dart

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,13 +1304,26 @@ class GlobalTime extends StatelessWidget {
13041304
final GlobalTimeNode node;
13051305
final TextStyle ambientTextStyle;
13061306

1307-
static final _dateFormat = intl.DateFormat('EEE, MMM d, y, h:mm a'); // TODO(i18n): localize date
1307+
static final _format12 =
1308+
intl.DateFormat('EEE, MMM d, y').addPattern('h:mm aa', ', ');
1309+
static final _format24 =
1310+
intl.DateFormat('EEE, MMM d, y').addPattern('Hm', ', ');
1311+
static final _formatLocaleDefault =
1312+
intl.DateFormat('EEE, MMM d, y').addPattern('jm', ', ');
13081313

13091314
@override
13101315
Widget build(BuildContext context) {
1316+
final store = PerAccountStoreWidget.of(context);
1317+
final twentyFourHourTimeMode = store.userSettings.twentyFourHourTime;
13111318
// Design taken from css for `.rendered_markdown & time` in web,
13121319
// see zulip:web/styles/rendered_markdown.css .
1313-
final text = _dateFormat.format(node.datetime.toLocal());
1320+
// TODO(i18n): localize; see plan with ffi in #45
1321+
final format = switch (twentyFourHourTimeMode) {
1322+
TwentyFourHourTimeMode.twelveHour => _format12,
1323+
TwentyFourHourTimeMode.twentyFourHour => _format24,
1324+
TwentyFourHourTimeMode.localeDefault => _formatLocaleDefault,
1325+
};
1326+
final text = format.format(node.datetime.toLocal());
13141327
final contentTheme = ContentTheme.of(context);
13151328
return Padding(
13161329
padding: const EdgeInsets.symmetric(horizontal: 2),

test/widgets/content_test.dart

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import 'package:flutter_checks/flutter_checks.dart';
77
import 'package:flutter_test/flutter_test.dart';
88
import 'package:url_launcher/url_launcher.dart';
99
import 'package:zulip/api/core.dart';
10+
import 'package:zulip/api/model/initial_snapshot.dart';
11+
import 'package:zulip/api/model/model.dart';
1012
import 'package:zulip/model/content.dart';
1113
import 'package:zulip/model/narrow.dart';
1214
import 'package:zulip/model/settings.dart';
@@ -118,9 +120,13 @@ Widget plainContent(String html) {
118120
Future<void> prepareContent(WidgetTester tester, Widget child, {
119121
List<NavigatorObserver> navObservers = const [],
120122
bool wrapWithPerAccountStoreWidget = false,
123+
InitialSnapshot? initialSnapshot,
121124
}) async {
122125
if (wrapWithPerAccountStoreWidget) {
123-
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
126+
initialSnapshot ??= eg.initialSnapshot();
127+
await testBinding.globalStore.add(eg.selfAccount, initialSnapshot);
128+
} else {
129+
assert(initialSnapshot == null);
124130
}
125131

126132
addTearDown(testBinding.reset);
@@ -598,10 +604,12 @@ void main() {
598604
Future<void> checkFontSizeRatio(WidgetTester tester, {
599605
required String targetHtml,
600606
required TargetFontSizeFinder targetFontSizeFinder,
607+
bool wrapWithPerAccountStoreWidget = false,
601608
}) async {
602-
await prepareContent(tester, plainContent(
603-
'<h1>header-plain $targetHtml</h1>\n'
604-
'<p>paragraph-plain $targetHtml</p>'));
609+
await prepareContent(tester, wrapWithPerAccountStoreWidget: wrapWithPerAccountStoreWidget,
610+
plainContent(
611+
'<h1>header-plain $targetHtml</h1>\n'
612+
'<p>paragraph-plain $targetHtml</p>'));
605613

606614
final headerRootSpan = tester.renderObject<RenderParagraph>(find.textContaining('header')).text;
607615
final headerPlainStyle = mergedStyleOfSubstring(headerRootSpan, 'header-plain ');
@@ -1071,16 +1079,52 @@ void main() {
10711079
// the timezone of the environment running these tests. Accept here a wide
10721080
// range of times. See comments in "show dates" test in
10731081
// `test/widgets/message_list_test.dart`.
1074-
final renderedTextRegexp = RegExp(r'^(Tue, Jan 30|Wed, Jan 31), 2024, \d+:\d\d [AP]M$');
1082+
final renderedTextRegexp = RegExp(r'^(Tue, Jan 30|Wed, Jan 31), 2024, \d+:\d\d(?: [AP]M)?$');
1083+
final renderedTextRegexpTwelveHour = RegExp(r'^(Tue, Jan 30|Wed, Jan 31), 2024, \d+:\d\d [AP]M$');
1084+
final renderedTextRegexpTwentyFourHour = RegExp(r'^(Tue, Jan 30|Wed, Jan 31), 2024, \d+:\d\d$');
1085+
1086+
Future<void> prepare(
1087+
WidgetTester tester,
1088+
[TwentyFourHourTimeMode twentyFourHourTimeMode = TwentyFourHourTimeMode.localeDefault]
1089+
) async {
1090+
final initialSnapshot = eg.initialSnapshot()
1091+
..userSettings.twentyFourHourTime = twentyFourHourTimeMode;
1092+
await prepareContent(tester,
1093+
// We use the self-account's time-format setting.
1094+
wrapWithPerAccountStoreWidget: true,
1095+
initialSnapshot: initialSnapshot,
1096+
plainContent('<p>$timeSpanHtml</p>'));
1097+
}
10751098

10761099
testWidgets('smoke', (tester) async {
1077-
await prepareContent(tester, plainContent('<p>$timeSpanHtml</p>'));
1100+
await prepare(tester);
10781101
tester.widget(find.textContaining(renderedTextRegexp));
10791102
});
10801103

1104+
testWidgets('TwentyFourHourTimeMode.twelveHour', (tester) async {
1105+
await prepare(tester, TwentyFourHourTimeMode.twelveHour);
1106+
check(find.textContaining(renderedTextRegexpTwelveHour)).findsOne();
1107+
});
1108+
1109+
testWidgets('TwentyFourHourTimeMode.twentyFourHour', (tester) async {
1110+
await prepare(tester, TwentyFourHourTimeMode.twentyFourHour);
1111+
check(find.textContaining(renderedTextRegexpTwentyFourHour)).findsOne();
1112+
});
1113+
1114+
testWidgets('TwentyFourHourTimeMode.localeDefault', (tester) async {
1115+
await prepare(tester, TwentyFourHourTimeMode.localeDefault);
1116+
// This expectation holds as long as we're always formatting in en_US,
1117+
// the default locale, which uses the twelve-hour format.
1118+
// TODO(#1727) follow the actual locale; test with different locales
1119+
check(find.textContaining(renderedTextRegexpTwelveHour)).findsOne();
1120+
});
1121+
10811122
void testIconAndTextSameColor(String description, String html) {
10821123
testWidgets('clock icon and text are the same color: $description', (tester) async {
1083-
await prepareContent(tester, plainContent(html));
1124+
await prepareContent(tester,
1125+
// We use the self-account's time-format setting.
1126+
wrapWithPerAccountStoreWidget: true,
1127+
plainContent(html));
10841128

10851129
final icon = tester.widget<Icon>(
10861130
find.descendant(of: find.byType(GlobalTime),
@@ -1100,6 +1144,8 @@ void main() {
11001144
group('maintains font-size ratio with surrounding text', () {
11011145
Future<void> doCheck(WidgetTester tester, double Function(GlobalTime widget) sizeFromWidget) async {
11021146
await checkFontSizeRatio(tester,
1147+
// We use the self-account's time-format setting.
1148+
wrapWithPerAccountStoreWidget: true,
11031149
targetHtml: '<time datetime="2024-01-30T17:33:00Z">2024-01-30T17:33:00Z</time>',
11041150
targetFontSizeFinder: (rootSpan) {
11051151
late final double result;

0 commit comments

Comments
 (0)