import 'package:commons_core/commons_core.dart'; import 'package:intl/intl.dart'; /// One row of the rendered chat: either a day separator or a message. Pure data /// so the grouping can be unit-tested without widgets. sealed class ChatTimelineItem { const ChatTimelineItem(); } /// A "— Today —" style divider before the first message of a calendar day. class ChatDaySeparator extends ChatTimelineItem { const ChatDaySeparator(this.day); /// Local midnight of the day this divider introduces. final DateTime day; } /// A chat bubble. class ChatMessageRow extends ChatTimelineItem { const ChatMessageRow(this.message); final PrivateMessage message; } /// Groups [messages] (oldest first) into a timeline, inserting a /// [ChatDaySeparator] before the first message of each local calendar day. /// Result stays oldest-first. List chatTimeline(List messages) { final out = []; DateTime? lastDay; for (final m in messages) { final day = DateTime(m.at.year, m.at.month, m.at.day); if (lastDay == null || day != lastDay) { out.add(ChatDaySeparator(day)); lastDay = day; } out.add(ChatMessageRow(m)); } return out; } /// The human label for a day separator: "Today"/"Yesterday" for the two most /// recent days (localized by the caller), otherwise a locale-formatted date /// (weekday + day + month, plus year when it differs from [now]). /// /// [localeCode] must be an `intl`-known locale — pass the *Localizations* locale /// (which maps Asturian → Spanish), never the raw app locale, since `ast` has no /// `intl` date symbols and would throw. Mirrors backup_section.dart. String chatDayLabel( DateTime day, { required DateTime now, required String today, required String yesterday, required String localeCode, }) { final startOfToday = DateTime(now.year, now.month, now.day); final startOfDay = DateTime(day.year, day.month, day.day); final diffDays = startOfToday.difference(startOfDay).inDays; if (diffDays == 0) return today; if (diffDays == 1) return yesterday; final format = day.year == now.year ? DateFormat.MMMMEEEEd(localeCode) : DateFormat.yMMMMEEEEd(localeCode); return format.format(day); } /// The clock time shown on a bubble, in the locale's own 12/24-hour convention. /// See [chatDayLabel] for the [localeCode] caveat. String chatBubbleTime(DateTime at, String localeCode) => DateFormat.jm(localeCode).format(at);