Telegram-iOS/submodules/TelegramCore/FlatSerialization/Models/RichText.fbs
isaac a731f8bdc0 Implement textDate autoformatter for InstantPage V2 rich bubbles
Render RichText.textDate (API constructor textDate(flags, text, date)) as a
locale/timezone-correct, relative-aware, tappable date inside V2 rich-message
bubbles, reusing the existing stringForEntityFormattedDate autoformatter.

- Model: add RichText.textDate(text📅format:) with Postbox coding,
  FlatBuffers schema (RichText.fbs; flatc regenerates), Equatable and plainText;
  parse flags->DateTimeFormat? at the API boundary (flags==0 => nil, matching
  the messageEntityFormattedDate convention) with a symmetric apiRichText()
  round-trip. The new case is handled in every exhaustive RichText switch
  (SyncCore, ApiUtils, InstantPageTextItem, InstantPageAnchorPath,
  InstantPagePreviewText, BrowserReadability, BrowserMarkdown).
- Render: attributedStringForRichText gains an optional formatDate closure;
  the V2 layout builds it from the message's strings/dateTimeFormat and threads
  it to every text-building call site, formatting the timestamp and tagging the
  run with TelegramTextAttributes.Date.
- Tappable: the Date attribute is added to linkSelectionRects hit-testing and
  mapped in the rich bubble's entityTapContent to the existing .date tap action
  (opens the date context menu).
- Live update: the V2 layout accumulates a page-wide formattedDateUpdatePeriod
  (>=10s) for relative dates; the rich bubble schedules a refresh timer on it,
  recreating it only when the period changes. The currentPageLayout cache is
  bypassed for relative-date pages so the timer-driven relayout actually
  re-formats the date.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 13:45:48 +02:00

164 lines
2.9 KiB
Text

include "MediaId.fbs";
include "PixelDimensions.fbs";
namespace TelegramCore;
union RichText_Value {
RichText_Empty,
RichText_Plain,
RichText_Bold,
RichText_Italic,
RichText_Underline,
RichText_Strikethrough,
RichText_Fixed,
RichText_Url,
RichText_Email,
RichText_Concat,
RichText_Subscript,
RichText_Superscript,
RichText_Marked,
RichText_Phone,
RichText_Image,
RichText_Anchor,
RichText_Formula,
RichText_CustomEmoji,
RichText_AutoEmail,
RichText_AutoPhone,
RichText_AutoUrl,
RichText_BankCard,
RichText_BotCommand,
RichText_Cashtag,
RichText_Hashtag,
RichText_Mention,
RichText_MentionName,
RichText_Spoiler,
RichText_Date
}
table RichText {
value:RichText_Value (id: 1, required);
}
table RichText_Empty {}
table RichText_Plain {
text:string (id: 0, required);
}
table RichText_Bold {
text:RichText (id: 0, required);
}
table RichText_Italic {
text:RichText (id: 0, required);
}
table RichText_Underline {
text:RichText (id: 0, required);
}
table RichText_Strikethrough {
text:RichText (id: 0, required);
}
table RichText_Fixed {
text:RichText (id: 0, required);
}
table RichText_Url {
text:RichText (id: 0, required);
url:string (id: 1, required);
webpageId:MediaId (id: 2);
}
table RichText_Email {
text:RichText (id: 0, required);
email:string (id: 1, required);
}
table RichText_Concat {
texts:[RichText] (id: 0, required);
}
table RichText_Subscript {
text:RichText (id: 0, required);
}
table RichText_Superscript {
text:RichText (id: 0, required);
}
table RichText_Marked {
text:RichText (id: 0, required);
}
table RichText_Phone {
text:RichText (id: 0, required);
phone:string (id: 1, required);
}
table RichText_Image {
id:MediaId (id: 0, required);
dimensions:PixelDimensions (id: 1, required);
}
table RichText_Anchor {
text:RichText (id: 0, required);
name:string (id: 1, required);
}
table RichText_Formula {
latex:string (id: 0, required);
}
table RichText_CustomEmoji {
fileId:long (id: 0);
alt:string (id: 1, required);
}
table RichText_AutoEmail {
text:RichText (id: 0, required);
}
table RichText_AutoPhone {
text:RichText (id: 0, required);
}
table RichText_AutoUrl {
text:RichText (id: 0, required);
}
table RichText_BankCard {
text:RichText (id: 0, required);
}
table RichText_BotCommand {
text:RichText (id: 0, required);
}
table RichText_Cashtag {
text:RichText (id: 0, required);
}
table RichText_Hashtag {
text:RichText (id: 0, required);
}
table RichText_Mention {
text:RichText (id: 0, required);
}
table RichText_MentionName {
text:RichText (id: 0, required);
peerId:long (id: 1);
}
table RichText_Spoiler {
text:RichText (id: 0, required);
}
table RichText_Date {
text:RichText (id: 0, required);
date:int (id: 1);
format:int = -1 (id: 2);
}