Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lightbox: Use a friendlier format for the date #1197

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions assets/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -680,5 +680,29 @@
"emojiPickerSearchEmoji": "Search emoji",
"@emojiPickerSearchEmoji": {
"description": "Hint text for the emoji picker search text field."
},
"aFewSecondsAgo": "A few seconds ago",
"@aFewSecondsAgo": {
"description": "Message displayed when the difference between the current time and the given time is less than 60 seconds."
},
"oneMinuteAgo": "1 minute ago",
"@oneMinuteAgo": {
"description": "Message displayed when the difference between the current time and the given time is exactly 1 minute."
},
"minutesAgo": "{minutes} minutes ago",
"@minutesAgo": {
"description": "Message displayed when the difference between the current time and the given time is in minutes. The placeholder {minutes} will be replaced with the actual number of minutes."
},
"todayAt": "Today at {time}",
"@todayAt": {
"description": "Message displayed when the given time is from today. The placeholder {time} will be replaced with the formatted time."
},
"yesterdayAt": "Yesterday at {time}",
"@yesterdayAt": {
"description": "Message displayed when the given time is from yesterday. The placeholder {time} will be replaced with the formatted time."
},
"dateAtTime": "{date} at {time}",
"@dateAtTime": {
"description": "Message displayed when the given time is older than yesterday. The placeholder {date} will be replaced with the formatted date and {time} with the formatted time."
}
}
36 changes: 36 additions & 0 deletions lib/generated/l10n/zulip_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,42 @@ abstract class ZulipLocalizations {
/// In en, this message translates to:
/// **'Search emoji'**
String get emojiPickerSearchEmoji;

/// Message displayed when the difference between the current time and the given time is less than 60 seconds.
///
/// In en, this message translates to:
/// **'A few seconds ago'**
String get aFewSecondsAgo;

/// Message displayed when the difference between the current time and the given time is exactly 1 minute.
///
/// In en, this message translates to:
/// **'1 minute ago'**
String get oneMinuteAgo;

/// Message displayed when the difference between the current time and the given time is in minutes. The placeholder {minutes} will be replaced with the actual number of minutes.
///
/// In en, this message translates to:
/// **'{minutes} minutes ago'**
String minutesAgo(Object minutes);

/// Message displayed when the given time is from today. The placeholder {time} will be replaced with the formatted time.
///
/// In en, this message translates to:
/// **'Today at {time}'**
String todayAt(Object time);

/// Message displayed when the given time is from yesterday. The placeholder {time} will be replaced with the formatted time.
///
/// In en, this message translates to:
/// **'Yesterday at {time}'**
String yesterdayAt(Object time);

/// Message displayed when the given time is older than yesterday. The placeholder {date} will be replaced with the formatted date and {time} with the formatted time.
///
/// In en, this message translates to:
/// **'{date} at {time}'**
String dateAtTime(Object date, Object time);
}

class _ZulipLocalizationsDelegate extends LocalizationsDelegate<ZulipLocalizations> {
Expand Down
26 changes: 26 additions & 0 deletions lib/generated/l10n/zulip_localizations_ar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -537,4 +537,30 @@ class ZulipLocalizationsAr extends ZulipLocalizations {

@override
String get emojiPickerSearchEmoji => 'Search emoji';

@override
String get aFewSecondsAgo => 'A few seconds ago';

@override
String get oneMinuteAgo => '1 minute ago';

@override
String minutesAgo(Object minutes) {
return '$minutes minutes ago';
}

@override
String todayAt(Object time) {
return 'Today at $time';
}

@override
String yesterdayAt(Object time) {
return 'Yesterday at $time';
}

@override
String dateAtTime(Object date, Object time) {
return '$date at $time';
}
}
26 changes: 26 additions & 0 deletions lib/generated/l10n/zulip_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -537,4 +537,30 @@ class ZulipLocalizationsEn extends ZulipLocalizations {

@override
String get emojiPickerSearchEmoji => 'Search emoji';

@override
String get aFewSecondsAgo => 'A few seconds ago';

@override
String get oneMinuteAgo => '1 minute ago';

@override
String minutesAgo(Object minutes) {
return '$minutes minutes ago';
}

@override
String todayAt(Object time) {
return 'Today at $time';
}

@override
String yesterdayAt(Object time) {
return 'Yesterday at $time';
}

@override
String dateAtTime(Object date, Object time) {
return '$date at $time';
}
}
26 changes: 26 additions & 0 deletions lib/generated/l10n/zulip_localizations_fr.dart
Original file line number Diff line number Diff line change
Expand Up @@ -537,4 +537,30 @@ class ZulipLocalizationsFr extends ZulipLocalizations {

@override
String get emojiPickerSearchEmoji => 'Search emoji';

@override
String get aFewSecondsAgo => 'A few seconds ago';

@override
String get oneMinuteAgo => '1 minute ago';

@override
String minutesAgo(Object minutes) {
return '$minutes minutes ago';
}

@override
String todayAt(Object time) {
return 'Today at $time';
}

@override
String yesterdayAt(Object time) {
return 'Yesterday at $time';
}

@override
String dateAtTime(Object date, Object time) {
return '$date at $time';
}
}
26 changes: 26 additions & 0 deletions lib/generated/l10n/zulip_localizations_ja.dart
Original file line number Diff line number Diff line change
Expand Up @@ -537,4 +537,30 @@ class ZulipLocalizationsJa extends ZulipLocalizations {

@override
String get emojiPickerSearchEmoji => 'Search emoji';

@override
String get aFewSecondsAgo => 'A few seconds ago';

@override
String get oneMinuteAgo => '1 minute ago';

@override
String minutesAgo(Object minutes) {
return '$minutes minutes ago';
}

@override
String todayAt(Object time) {
return 'Today at $time';
}

@override
String yesterdayAt(Object time) {
return 'Yesterday at $time';
}

@override
String dateAtTime(Object date, Object time) {
return '$date at $time';
}
}
26 changes: 26 additions & 0 deletions lib/generated/l10n/zulip_localizations_pl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -537,4 +537,30 @@ class ZulipLocalizationsPl extends ZulipLocalizations {

@override
String get emojiPickerSearchEmoji => 'Search emoji';

@override
String get aFewSecondsAgo => 'A few seconds ago';

@override
String get oneMinuteAgo => '1 minute ago';

@override
String minutesAgo(Object minutes) {
return '$minutes minutes ago';
}

@override
String todayAt(Object time) {
return 'Today at $time';
}

@override
String yesterdayAt(Object time) {
return 'Yesterday at $time';
}

@override
String dateAtTime(Object date, Object time) {
return '$date at $time';
}
}
26 changes: 26 additions & 0 deletions lib/generated/l10n/zulip_localizations_ru.dart
Original file line number Diff line number Diff line change
Expand Up @@ -537,4 +537,30 @@ class ZulipLocalizationsRu extends ZulipLocalizations {

@override
String get emojiPickerSearchEmoji => 'Search emoji';

@override
String get aFewSecondsAgo => 'A few seconds ago';

@override
String get oneMinuteAgo => '1 minute ago';

@override
String minutesAgo(Object minutes) {
return '$minutes minutes ago';
}

@override
String todayAt(Object time) {
return 'Today at $time';
}

@override
String yesterdayAt(Object time) {
return 'Yesterday at $time';
}

@override
String dateAtTime(Object date, Object time) {
return '$date at $time';
}
}
41 changes: 36 additions & 5 deletions lib/widgets/lightbox.dart
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,42 @@ class _LightboxPageLayoutState extends State<_LightboxPageLayout> {

PreferredSizeWidget? appBar;
if (_headerFooterVisible) {
// TODO(#45): Format with e.g. "Yesterday at 4:47 PM"
final timestampText = DateFormat
.yMMMd(/* TODO(#278): Pass selected language here, I think? */)
.add_Hms()
.format(DateTime.fromMillisecondsSinceEpoch(widget.message.timestamp * 1000));
final zulipLocalizations = ZulipLocalizations.of(context);

String formatLocalizedTimestamp(DateTime date) {
final now = DateTime.now();
final nowDateOnly = DateTime(now.year, now.month, now.day);
final messageDateOnly = DateTime(date.year, date.month, date.day);

final differenceInSeconds = now.difference(date).inSeconds;
final differenceInMinutes = now.difference(date).inMinutes;
final differenceInDays = nowDateOnly.difference(messageDateOnly).inDays;

if (differenceInSeconds < 60) {
return zulipLocalizations.aFewSecondsAgo;
} else if (differenceInMinutes < 60) {
return Intl.plural(
differenceInMinutes,
one: zulipLocalizations.oneMinuteAgo,
other: zulipLocalizations.minutesAgo(differenceInMinutes),
locale: zulipLocalizations.localeName,
);
} else if (differenceInDays == 0) {
final time = DateFormat.jm(zulipLocalizations.localeName).format(date);
return zulipLocalizations.todayAt(time);
} else if (differenceInDays == 1) {
final time = DateFormat.jm(zulipLocalizations.localeName).format(date);
return zulipLocalizations.yesterdayAt(time);
} else {
final dateStr = DateFormat('MMM d, yyyy', zulipLocalizations.localeName).format(date);
final timeStr = DateFormat('hh:mm a', zulipLocalizations.localeName).format(date);
return zulipLocalizations.dateAtTime(dateStr, timeStr);
}
}

final timestampText = formatLocalizedTimestamp(
DateTime.fromMillisecondsSinceEpoch(widget.message.timestamp * 1000),
);

// We use plain [AppBar] instead of [ZulipAppBar], even though this page
// has a [PerAccountStore], because:
Expand Down
2 changes: 1 addition & 1 deletion test/widgets/lightbox_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ void main() {
matching: find.textContaining(findRichText: true,
eg.otherUser.fullName)));
check(labelTextWidget.text.toPlainText())
.contains('Jul 23, 2024 23:12:24');
.contains('Jul 23, 2024 at 11:12 PM');
Copy link

@apoorvapendse apoorvapendse Dec 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should add checks for the other behaviors as well like "a few minutes ago".


debugNetworkImageHttpClientProvider = null;
});
Expand Down