Skip to content

Commit 3703baa

Browse files
chrisbobbegnprice
authored andcommitted
msglist [nfc]: Finish centralizing on MessageTimestampStyle
1 parent 7704fd8 commit 3703baa

File tree

2 files changed

+75
-69
lines changed

2 files changed

+75
-69
lines changed

lib/widgets/message_list.dart

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,10 @@ class DateText extends StatelessWidget {
18431843
Widget build(BuildContext context) {
18441844
final messageListTheme = MessageListTheme.of(context);
18451845
final zulipLocalizations = ZulipLocalizations.of(context);
1846+
final formattedTimestamp = MessageTimestampStyle.dateOnlyRelative.format(
1847+
timestamp,
1848+
now: ZulipBinding.instance.utcNow().toLocal(),
1849+
zulipLocalizations: zulipLocalizations)!;
18461850
return Text(
18471851
style: TextStyle(
18481852
color: messageListTheme.labelTime,
@@ -1852,46 +1856,7 @@ class DateText extends StatelessWidget {
18521856
// https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-caps#all-small-caps
18531857
fontFeatures: const [FontFeature.enable('c2sc'), FontFeature.enable('smcp')],
18541858
),
1855-
formatHeaderDate(
1856-
zulipLocalizations,
1857-
DateTime.fromMillisecondsSinceEpoch(timestamp * 1000),
1858-
now: ZulipBinding.instance.utcNow().toLocal()));
1859-
}
1860-
}
1861-
1862-
@visibleForTesting
1863-
String formatHeaderDate(
1864-
ZulipLocalizations zulipLocalizations,
1865-
DateTime dateTime, {
1866-
required DateTime now,
1867-
}) {
1868-
assert(!dateTime.isUtc && !now.isUtc,
1869-
'`dateTime` and `now` need to be in local time.');
1870-
1871-
if (dateTime.year == now.year &&
1872-
dateTime.month == now.month &&
1873-
dateTime.day == now.day) {
1874-
return zulipLocalizations.today;
1875-
}
1876-
1877-
final yesterday = now
1878-
.copyWith(hour: 12, minute: 0, second: 0, millisecond: 0, microsecond: 0)
1879-
.add(const Duration(days: -1));
1880-
if (dateTime.year == yesterday.year &&
1881-
dateTime.month == yesterday.month &&
1882-
dateTime.day == yesterday.day) {
1883-
return zulipLocalizations.yesterday;
1884-
}
1885-
1886-
// If it is Dec 1 and you see a label that says `Dec 2`
1887-
// it could be misinterpreted as Dec 2 of the previous
1888-
// year. For times in the future, those still on the
1889-
// current day will show as today (handled above) and
1890-
// any dates beyond that show up with the year.
1891-
if (dateTime.year == now.year && dateTime.isBefore(now)) {
1892-
return DateFormat.MMMd().format(dateTime);
1893-
} else {
1894-
return DateFormat.yMMMd().format(dateTime);
1859+
formattedTimestamp);
18951860
}
18961861
}
18971862

@@ -1985,9 +1950,9 @@ class SenderRow extends StatelessWidget {
19851950
}
19861951
}
19871952

1988-
// TODO centralize on this for wherever we show message timestamps
19891953
enum MessageTimestampStyle {
19901954
none,
1955+
dateOnlyRelative,
19911956
timeOnly,
19921957

19931958
// TODO(#45): E.g. "Yesterday at 4:47 PM"; see details in #45
@@ -2007,6 +1972,40 @@ enum MessageTimestampStyle {
20071972
full,
20081973
;
20091974

1975+
static String _formatDateOnlyRelative(
1976+
DateTime dateTime, {
1977+
required DateTime now,
1978+
required ZulipLocalizations zulipLocalizations,
1979+
}) {
1980+
assert(!dateTime.isUtc && !now.isUtc,
1981+
'`dateTime` and `now` need to be in local time.');
1982+
1983+
if (dateTime.year == now.year &&
1984+
dateTime.month == now.month &&
1985+
dateTime.day == now.day) {
1986+
return zulipLocalizations.today;
1987+
}
1988+
1989+
final yesterday = now
1990+
.copyWith(hour: 12, minute: 0, second: 0, millisecond: 0, microsecond: 0)
1991+
.add(const Duration(days: -1));
1992+
if (dateTime.year == yesterday.year &&
1993+
dateTime.month == yesterday.month &&
1994+
dateTime.day == yesterday.day) {
1995+
return zulipLocalizations.yesterday;
1996+
}
1997+
1998+
// If it is Dec 1 and you see a label that says `Dec 2`
1999+
// it could be misinterpreted as Dec 2 of the previous
2000+
// year. For times in the future, those still on the
2001+
// current day will show as today (handled above) and
2002+
// any dates beyond that show up with the year.
2003+
if (dateTime.year == now.year && dateTime.isBefore(now)) {
2004+
return DateFormat.MMMd().format(dateTime);
2005+
} else {
2006+
return DateFormat.yMMMd().format(dateTime);
2007+
}
2008+
}
20102009
static final _timeOnlyFormat = DateFormat('h:mm aa', 'en_US');
20112010
static final _lightboxFormat = DateFormat.yMMMd().add_Hms();
20122011
static final _fullFormat = DateFormat.yMMMd().add_jm();
@@ -2023,6 +2022,9 @@ enum MessageTimestampStyle {
20232022

20242023
switch (this) {
20252024
case none: return null;
2025+
case dateOnlyRelative:
2026+
return _formatDateOnlyRelative(asDateTime,
2027+
now: now, zulipLocalizations: zulipLocalizations);
20262028
case timeOnly: return _timeOnlyFormat.format(asDateTime);
20272029
case lightbox: return _lightboxFormat.format(asDateTime);
20282030
case full: return _fullFormat.format(asDateTime);

test/widgets/message_list_test.dart

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,35 +1638,39 @@ void main() {
16381638
});
16391639
});
16401640

1641-
group('formatHeaderDate', () {
1642-
final zulipLocalizations = GlobalLocalizations.zulipLocalizations;
1643-
final now = DateTime.parse("2023-01-10 12:00");
1644-
final testCases = [
1645-
("2023-01-10 12:00", zulipLocalizations.today),
1646-
("2023-01-10 00:00", zulipLocalizations.today),
1647-
("2023-01-10 23:59", zulipLocalizations.today),
1648-
("2023-01-09 23:59", zulipLocalizations.yesterday),
1649-
("2023-01-09 00:00", zulipLocalizations.yesterday),
1650-
("2023-01-08 00:00", "Jan 8"),
1651-
("2022-12-31 00:00", "Dec 31, 2022"),
1652-
// Future times
1653-
("2023-01-10 19:00", zulipLocalizations.today),
1654-
("2023-01-11 00:00", "Jan 11, 2023"),
1655-
];
1656-
for (final (dateTime, expected) in testCases) {
1657-
test('$dateTime returns $expected', () {
1658-
addTearDown(testBinding.reset);
1659-
1660-
withClock(Clock.fixed(now), () {
1661-
check(formatHeaderDate(
1662-
zulipLocalizations,
1663-
DateTime.parse(dateTime),
1664-
now: testBinding.utcNow().toLocal(),
1665-
))
1666-
.equals(expected);
1641+
group('MessageTimestampStyle', () {
1642+
group('dateOnlyRelative', () {
1643+
final zulipLocalizations = GlobalLocalizations.zulipLocalizations;
1644+
final now = DateTime.parse("2023-01-10 12:00");
1645+
final testCases = [
1646+
("2023-01-10 12:00", zulipLocalizations.today),
1647+
("2023-01-10 00:00", zulipLocalizations.today),
1648+
("2023-01-10 23:59", zulipLocalizations.today),
1649+
("2023-01-09 23:59", zulipLocalizations.yesterday),
1650+
("2023-01-09 00:00", zulipLocalizations.yesterday),
1651+
("2023-01-08 00:00", "Jan 8"),
1652+
("2022-12-31 00:00", "Dec 31, 2022"),
1653+
// Future times
1654+
("2023-01-10 19:00", zulipLocalizations.today),
1655+
("2023-01-11 00:00", "Jan 11, 2023"),
1656+
];
1657+
for (final (dateTime, expected) in testCases) {
1658+
test('$dateTime returns $expected', () {
1659+
addTearDown(testBinding.reset);
1660+
1661+
withClock(Clock.fixed(now), () {
1662+
final timestamp = DateTime.parse(dateTime).millisecondsSinceEpoch ~/ 1000;
1663+
final result = MessageTimestampStyle.dateOnlyRelative.format(
1664+
timestamp,
1665+
now: testBinding.utcNow().toLocal(),
1666+
zulipLocalizations: zulipLocalizations);
1667+
check(result).equals(expected);
1668+
});
16671669
});
1668-
});
1669-
}
1670+
}
1671+
});
1672+
1673+
// TODO others
16701674
});
16711675

16721676
group('MessageWithPossibleSender', () {

0 commit comments

Comments
 (0)