/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "history/history_inner_widget_accessibility.h" #include "base/unixtime.h" #include "data/data_document.h" #include "data/data_game.h" #include "data/data_media_types.h" #include "data/data_message_reaction_id.h" #include "data/data_photo.h" #include "data/data_poll.h" #include "data/data_session.h" #include "data/data_todo_list.h" #include "data/data_user.h" #include "data/data_web_page.h" #include "history/view/history_view_element.h" #include "history/history.h" #include "history/history_item.h" #include "history/history_item_components.h" #include "lang/lang_keys.h" #include "ui/text/format_values.h" namespace HistoryView { QString MessageAccessibilityName( not_null view, not_null history) { const auto item = view->data(); if (item->isService()) { const auto text = item->notificationText().text; return text.isEmpty() ? QString() : text; } QStringList lines; if (item->out()) { lines.push_back(item->unread(history) ? tr::lng_sr_message_not_seen(tr::now) : tr::lng_sr_message_seen(tr::now)); } if (item->out()) { lines.push_back(tr::lng_sr_from_me(tr::now)); } else if (const auto from = item->displayFrom()) { lines.push_back(from->name()); } if (const auto bot = item->viaBot()) { lines.push_back(tr::lng_inline_bot_via( tr::now, lt_inline_bot, '@' + bot->username())); } if (const auto reply = item->Get()) { if (const auto message = reply->resolvedMessage.get()) { const auto replyFrom = message->displayFrom(); const auto replyName = replyFrom ? replyFrom->name() : QString(); const auto replyText = message->inReplyText().text; if (!replyName.isEmpty() || !replyText.isEmpty()) { lines.push_back(tr::lng_sr_message_reply_to( tr::now, lt_name, replyName.isEmpty() ? tr::lng_sr_from_me(tr::now) : replyName, lt_text, replyText)); } } } if (const auto forwarded = item->Get()) { if (forwarded->originalSender) { lines.push_back(tr::lng_forwarded( tr::now, lt_user, forwarded->originalSender->name())); } else if (forwarded->originalHiddenSenderInfo) { lines.push_back(tr::lng_forwarded( tr::now, lt_user, forwarded->originalHiddenSenderInfo->name)); } } if (const auto media = item->media()) { QStringList mediaParts; if (const auto document = media->document()) { if (document->isVoiceMessage()) { mediaParts.push_back(tr::lng_in_dlg_audio(tr::now)); } else if (document->isVideoMessage()) { mediaParts.push_back(tr::lng_in_dlg_video_message(tr::now)); } else if (document->isSong()) { mediaParts.push_back(tr::lng_in_dlg_audio_file(tr::now)); } else if (document->isVideoFile()) { mediaParts.push_back(tr::lng_in_dlg_video(tr::now)); } else if (document->isAnimation()) { mediaParts.push_back(u"GIF"_q); } else if (const auto sticker = document->sticker()) { mediaParts.push_back(tr::lng_in_dlg_sticker(tr::now)); if (!sticker->alt.isEmpty()) { mediaParts.push_back(sticker->alt); } } else { mediaParts.push_back(tr::lng_in_dlg_file(tr::now)); } if (document->loading()) { mediaParts.push_back( tr::lng_sr_message_downloading(tr::now)); } else if (!document->filepath(true).isEmpty() || document->loadedInMediaCache()) { mediaParts.push_back( tr::lng_emoji_set_ready(tr::now)); } else { mediaParts.push_back( tr::lng_sr_message_not_downloaded(tr::now)); } if (document->isVoiceMessage() || document->isVideoMessage()) { mediaParts.push_back(item->isUnreadMedia() ? tr::lng_sr_message_not_played(tr::now) : tr::lng_sr_message_played(tr::now)); } if (const auto song = document->song()) { if (!song->performer.isEmpty()) { mediaParts.push_back(song->performer); } if (!song->title.isEmpty()) { mediaParts.push_back(song->title); } } if (!document->isSong() && !document->isVoiceMessage() && !document->isVideoMessage() && !document->sticker()) { const auto name = document->filename(); if (!name.isEmpty()) { mediaParts.push_back(name); } } const auto duration = document->duration(); if (duration > 0) { mediaParts.push_back( Ui::FormatDurationText(duration / 1000)); } if (!document->dimensions.isEmpty() && (document->isVideoFile() || document->isImage())) { mediaParts.push_back( Ui::FormatImageSizeText(document->dimensions)); } if (document->size > 0) { mediaParts.push_back( Ui::FormatSizeText(document->size)); } } else if (const auto photo = media->photo()) { mediaParts.push_back(tr::lng_in_dlg_photo(tr::now)); if (media->hasSpoiler()) { mediaParts.push_back( tr::lng_sr_message_spoiler(tr::now)); } const auto large = photo->size( Data::PhotoSize::Large); if (large && !large->isEmpty()) { mediaParts.push_back( Ui::FormatImageSizeText(*large)); } } else if (const auto call = media->call()) { const auto notification = item->notificationText().text; if (!notification.isEmpty()) { mediaParts.push_back(notification); } if (call->duration > 0) { mediaParts.push_back( Ui::FormatDurationText(call->duration)); } } else if (const auto poll = media->poll()) { mediaParts.push_back(poll->quiz() ? tr::lng_polls_public_quiz(tr::now) : tr::lng_polls_public(tr::now)); if (!poll->question.text.isEmpty()) { mediaParts.push_back(poll->question.text); } if (poll->closed()) { mediaParts.push_back( tr::lng_hours_closed(tr::now)); } mediaParts.push_back(tr::lng_polls_votes_count( tr::now, lt_count, poll->totalVoters)); } else if (const auto contact = media->sharedContact()) { auto contactName = contact->firstName; if (!contact->lastName.isEmpty()) { if (!contactName.isEmpty()) { contactName += u" "_q; } contactName += contact->lastName; } if (!contactName.isEmpty()) { mediaParts.push_back(contactName); } if (!contact->phoneNumber.isEmpty()) { mediaParts.push_back(contact->phoneNumber); } } else if (media->location()) { mediaParts.push_back(item->notificationText().text); } else if (const auto game = media->game()) { if (!game->title.isEmpty()) { mediaParts.push_back(game->title); } } else if (const auto invoice = media->invoice()) { if (!invoice->title.isEmpty()) { mediaParts.push_back(invoice->title); } mediaParts.push_back(invoice->currency + u" "_q + QString::number(invoice->amount / 100.0, 'f', 2)); } else if (const auto gift = media->gift()) { switch (gift->type) { case Data::GiftType::Premium: mediaParts.push_back( tr::lng_sr_message_gift_premium( tr::now, lt_count, gift->count)); break; case Data::GiftType::Credits: case Data::GiftType::StarGift: mediaParts.push_back( tr::lng_sr_message_gift_credits( tr::now, lt_count, gift->count)); break; default: if (!gift->giftTitle.isEmpty()) { mediaParts.push_back(gift->giftTitle); } break; } } else if (const auto todolist = media->todolist()) { if (!todolist->title.text.isEmpty()) { mediaParts.push_back(todolist->title.text); } } else if (media->giveawayStart() || media->giveawayResults()) { mediaParts.push_back(item->notificationText().text); } else { const auto notification = item->notificationText().text; if (!notification.isEmpty()) { mediaParts.push_back(notification); } } if (!mediaParts.isEmpty()) { lines.push_back(mediaParts.join(u", "_q)); } if (const auto webpage = media->webpage()) { QStringList webParts; if (!webpage->siteName.isEmpty()) { webParts.push_back(webpage->siteName); } if (!webpage->title.isEmpty()) { webParts.push_back(webpage->title); } if (!webpage->description.text.isEmpty()) { webParts.push_back(webpage->description.text); } if (!webParts.isEmpty()) { lines.push_back(webParts.join(u": "_q)); } } const auto &caption = item->originalText().text; if (!caption.isEmpty()) { lines.push_back(caption); } } else { const auto &text = item->originalText().text; if (!text.isEmpty()) { lines.push_back(text); } } const auto factcheck = item->factcheckText(); if (!factcheck.empty()) { lines.push_back(factcheck.text); } if (item->isPinned()) { lines.push_back(tr::lng_sr_chat_pinned(tr::now)); } QStringList statusParts; if (item->out()) { if (item->isSending()) { statusParts.push_back(tr::lng_sr_chat_sending(tr::now)); } else if (item->hasFailed()) { statusParts.push_back(tr::lng_sr_chat_failed(tr::now)); } else { statusParts.push_back(tr::lng_sr_chat_sent(tr::now)); } } else { statusParts.push_back(tr::lng_sr_chat_received(tr::now)); } if (item->Has()) { statusParts.push_back(tr::lng_edited(tr::now)); } const auto dateTime = view->dateTime(); statusParts.push_back( tr::lng_schedule_at(tr::now) + u" "_q + QLocale().toString(dateTime.time(), QLocale::ShortFormat)); if (const auto views = item->Get()) { if (views->views.count >= 0) { statusParts.push_back( QString::number(views->views.count) + u" "_q + tr::lng_stats_overview_message_views(tr::now)); } } if (const auto signed_ = item->Get()) { if (!signed_->author.isEmpty()) { statusParts.push_back(signed_->author); } } lines.push_back(statusParts.join(u" "_q)); const auto &reactions = item->reactions(); if (!reactions.empty()) { QStringList reactionParts; for (const auto &reaction : reactions) { auto text = reaction.id.emoji(); if (text.isEmpty()) { if (const auto customId = reaction.id.custom()) { const auto doc = item->history()->owner().document( customId); if (const auto sticker = doc->sticker()) { text = tr::lng_sr_message_custom_emoji( tr::now, lt_emoji, sticker->alt); } } } if (!text.isEmpty()) { if (reaction.count > 1) { reactionParts.push_back( text + u" "_q + QString::number(reaction.count)); } else { reactionParts.push_back(text); } } } if (!reactionParts.isEmpty()) { lines.push_back(tr::lng_notification_reactions(tr::now) + u": "_q + reactionParts.join(u", "_q)); } } return lines.join(u"\n"_q); } QString UnreadBarAccessibilityName(not_null barElement) { if (const auto bar = barElement->Get()) { return bar->text; } return tr::lng_unread_bar_some(tr::now); } QString MessageSubItemLabel(MessageSubItem item) { switch (item) { case MessageSubItem::Seen: return tr::lng_sr_message_seen(tr::now); case MessageSubItem::Sender: return tr::lng_sr_chat_column_sender(tr::now); case MessageSubItem::ViaBot: return tr::lng_inline_bot_via(tr::now, lt_inline_bot, QString()); case MessageSubItem::Reply: return tr::lng_notification_reply(tr::now); case MessageSubItem::Forward: return tr::lng_sr_chat_column_forward(tr::now); case MessageSubItem::MediaType: return tr::lng_sr_message_column_media_type(tr::now); case MessageSubItem::Download: return tr::lng_media_download(tr::now); case MessageSubItem::Played: return tr::lng_sr_message_played(tr::now); case MessageSubItem::Artist: return tr::lng_sr_message_column_artist(tr::now); case MessageSubItem::Title: return tr::lng_sr_message_column_title(tr::now); case MessageSubItem::Filename: return tr::lng_sr_message_column_filename(tr::now); case MessageSubItem::Duration: return tr::lng_sr_message_column_duration(tr::now); case MessageSubItem::Dimensions: return tr::lng_sr_message_column_dimensions(tr::now); case MessageSubItem::FileSize: return tr::lng_sr_message_column_file_size(tr::now); case MessageSubItem::Message: return tr::lng_sr_chat_column_message(tr::now); case MessageSubItem::Delivery: return tr::lng_sr_chat_column_delivery(tr::now); case MessageSubItem::Edited: return tr::lng_edited(tr::now); case MessageSubItem::Time: return tr::lng_sr_chat_column_time(tr::now); case MessageSubItem::Reactions: return tr::lng_notification_reactions(tr::now); case MessageSubItem::Views: return tr::lng_stats_overview_message_views(tr::now); case MessageSubItem::Signature: return tr::lng_sr_message_column_signature(tr::now); case MessageSubItem::Pinned: return tr::lng_sr_chat_pinned(tr::now); case MessageSubItem::WebSite: return tr::lng_sr_message_column_web_site(tr::now); case MessageSubItem::WebTitle: return tr::lng_sr_message_column_web_title(tr::now); case MessageSubItem::WebDescription: return tr::lng_sr_message_column_web_description(tr::now); case MessageSubItem::PollQuestion: return tr::lng_sr_message_column_poll_question(tr::now); case MessageSubItem::PollOptions: return tr::lng_polls_create_options(tr::now); case MessageSubItem::PollStatus: return tr::lng_sr_message_column_poll_status(tr::now); case MessageSubItem::ContactName: return tr::lng_sr_message_column_contact_name(tr::now); case MessageSubItem::ContactPhone: return tr::lng_sr_message_column_contact_phone(tr::now); case MessageSubItem::Location: return tr::lng_sr_message_column_location(tr::now); case MessageSubItem::StickerEmoji: return tr::lng_sr_message_column_sticker_emoji(tr::now); case MessageSubItem::GameTitle: return tr::lng_sr_message_column_game_title(tr::now); case MessageSubItem::GameDescription: return tr::lng_sr_message_column_game_description(tr::now); case MessageSubItem::InvoiceTitle: return tr::lng_sr_message_column_invoice_title(tr::now); case MessageSubItem::InvoiceAmount: return tr::lng_sr_message_column_invoice_amount(tr::now); case MessageSubItem::Spoiler: return tr::lng_sr_message_column_spoiler(tr::now); case MessageSubItem::Dice: return tr::lng_sr_message_column_dice(tr::now); case MessageSubItem::Giveaway: return tr::lng_sr_message_column_giveaway(tr::now); case MessageSubItem::Gift: return tr::lng_sr_message_column_gift(tr::now); case MessageSubItem::TodoTitle: return tr::lng_sr_message_column_todo_title(tr::now); case MessageSubItem::TodoItems: return tr::lng_sr_message_column_todo_items(tr::now); case MessageSubItem::Factcheck: return tr::lng_sr_message_column_factcheck(tr::now); case MessageSubItem::ForwardDate: return tr::lng_sr_message_column_forward_date(tr::now); case MessageSubItem::ForwardAuthor: return tr::lng_sr_message_column_forward_author(tr::now); case MessageSubItem::PaidReactions: return tr::lng_sr_message_column_paid_reactions(tr::now); case MessageSubItem::Count: break; } return {}; } QString MessageSubItemValue( not_null view, not_null history, MessageSubItem item) { const auto data = view->data(); if (data->isService()) { if (item == MessageSubItem::Message) { return data->notificationText().text; } return {}; } switch (item) { case MessageSubItem::Seen: if (data->out()) { return data->unread(history) ? tr::lng_sr_message_not_seen(tr::now) : tr::lng_sr_message_seen(tr::now); } return {}; case MessageSubItem::Sender: if (data->out()) { return tr::lng_sr_from_me(tr::now); } else if (const auto from = data->displayFrom()) { return from->name(); } return {}; case MessageSubItem::ViaBot: if (const auto bot = data->viaBot()) { return tr::lng_inline_bot_via( tr::now, lt_inline_bot, '@' + bot->username()); } return {}; case MessageSubItem::Reply: if (const auto reply = data->Get()) { if (const auto message = reply->resolvedMessage.get()) { const auto replyFrom = message->displayFrom(); const auto replyName = replyFrom ? replyFrom->name() : QString(); const auto replyText = message->inReplyText().text; if (!replyName.isEmpty() || !replyText.isEmpty()) { return tr::lng_sr_message_reply_to( tr::now, lt_name, replyName.isEmpty() ? tr::lng_sr_from_me(tr::now) : replyName, lt_text, replyText); } } } return {}; case MessageSubItem::Forward: if (const auto fwd = data->Get()) { if (fwd->originalSender) { return tr::lng_forwarded( tr::now, lt_user, fwd->originalSender->name()); } else if (fwd->originalHiddenSenderInfo) { return tr::lng_forwarded( tr::now, lt_user, fwd->originalHiddenSenderInfo->name); } } return {}; case MessageSubItem::MediaType: { const auto media = data->media(); if (!media) { return {}; } if (const auto document = media->document()) { if (document->isVoiceMessage()) { return tr::lng_in_dlg_audio(tr::now); } else if (document->isVideoMessage()) { return tr::lng_in_dlg_video_message(tr::now); } else if (document->isSong()) { return tr::lng_in_dlg_audio_file(tr::now); } else if (document->isVideoFile()) { return tr::lng_in_dlg_video(tr::now); } else if (document->isAnimation()) { return u"GIF"_q; } else if (document->sticker()) { return tr::lng_in_dlg_sticker(tr::now); } return tr::lng_in_dlg_file(tr::now); } else if (media->photo()) { return tr::lng_in_dlg_photo(tr::now); } else if (media->call()) { return data->notificationText().text; } return data->notificationText().text; } case MessageSubItem::Download: { const auto media = data->media(); if (!media) { return {}; } const auto document = media->document(); if (!document) { return {}; } if (document->loading()) { return tr::lng_sr_message_downloading(tr::now); } else if (!document->filepath(true).isEmpty() || document->loadedInMediaCache()) { return tr::lng_emoji_set_ready(tr::now); } return tr::lng_sr_message_not_downloaded(tr::now); } case MessageSubItem::Played: { const auto media = data->media(); if (!media) { return {}; } const auto document = media->document(); if (!document) { return {}; } if (document->isVoiceMessage() || document->isVideoMessage()) { return data->isUnreadMedia() ? tr::lng_sr_message_not_played(tr::now) : tr::lng_sr_message_played(tr::now); } return {}; } case MessageSubItem::Artist: { const auto media = data->media(); if (!media) { return {}; } const auto document = media->document(); if (!document) { return {}; } if (const auto song = document->song()) { return song->performer; } return {}; } case MessageSubItem::Title: { const auto media = data->media(); if (!media) { return {}; } const auto document = media->document(); if (!document) { return {}; } if (const auto song = document->song()) { return song->title; } return {}; } case MessageSubItem::Filename: { const auto media = data->media(); if (!media) { return {}; } const auto document = media->document(); if (!document || document->isSong() || document->isVoiceMessage() || document->isVideoMessage() || document->sticker()) { return {}; } return document->filename(); } case MessageSubItem::Duration: { const auto media = data->media(); if (!media) { return {}; } if (const auto document = media->document()) { const auto duration = document->duration(); if (duration > 0) { return Ui::FormatDurationText(duration / 1000); } } else if (const auto call = media->call()) { if (call->duration > 0) { return Ui::FormatDurationText(call->duration); } } return {}; } case MessageSubItem::Dimensions: { const auto media = data->media(); if (!media) { return {}; } if (const auto document = media->document()) { if (!document->dimensions.isEmpty() && (document->isVideoFile() || document->isImage())) { return Ui::FormatImageSizeText(document->dimensions); } } else if (const auto photo = media->photo()) { const auto large = photo->size( Data::PhotoSize::Large); if (large && !large->isEmpty()) { return Ui::FormatImageSizeText(*large); } } return {}; } case MessageSubItem::FileSize: { const auto media = data->media(); if (!media) { return {}; } const auto document = media->document(); if (!document || document->size <= 0) { return {}; } return Ui::FormatSizeText(document->size); } case MessageSubItem::Message: { if (data->media()) { return data->originalText().text; } return data->originalText().text; } case MessageSubItem::Delivery: if (data->out()) { if (data->isSending()) { return tr::lng_sr_chat_sending(tr::now); } else if (data->hasFailed()) { return tr::lng_sr_chat_failed(tr::now); } return tr::lng_sr_chat_sent(tr::now); } return tr::lng_sr_chat_received(tr::now); case MessageSubItem::Edited: if (data->Has()) { return tr::lng_edited(tr::now); } return {}; case MessageSubItem::Time: { const auto dateTime = view->dateTime(); return tr::lng_schedule_at(tr::now) + u" "_q + QLocale().toString(dateTime.time(), QLocale::ShortFormat); } case MessageSubItem::Reactions: { const auto &reactions = data->reactions(); if (reactions.empty()) { return {}; } QStringList reactionParts; for (const auto &reaction : reactions) { auto text = reaction.id.emoji(); if (text.isEmpty()) { if (const auto customId = reaction.id.custom()) { const auto doc = data->history()->owner().document( customId); if (const auto sticker = doc->sticker()) { text = tr::lng_sr_message_custom_emoji( tr::now, lt_emoji, sticker->alt); } } } if (!text.isEmpty()) { if (reaction.count > 1) { reactionParts.push_back( text + u" "_q + QString::number(reaction.count)); } else { reactionParts.push_back(text); } } } return reactionParts.join(u", "_q); } case MessageSubItem::Views: { const auto views = data->Get(); if (views && views->views.count >= 0) { return QString::number(views->views.count); } return {}; } case MessageSubItem::Signature: { const auto signed_ = data->Get(); if (signed_ && !signed_->author.isEmpty()) { return signed_->author; } return {}; } case MessageSubItem::Pinned: if (data->isPinned()) { return tr::lng_sr_chat_pinned(tr::now); } return {}; case MessageSubItem::WebSite: { const auto media = data->media(); if (!media) { return {}; } const auto webpage = media->webpage(); if (webpage) { return webpage->siteName; } return {}; } case MessageSubItem::WebTitle: { const auto media = data->media(); if (!media) { return {}; } const auto webpage = media->webpage(); if (webpage) { return webpage->title; } return {}; } case MessageSubItem::WebDescription: { const auto media = data->media(); if (!media) { return {}; } const auto webpage = media->webpage(); if (webpage) { return webpage->description.text; } return {}; } case MessageSubItem::PollQuestion: { const auto media = data->media(); if (!media) { return {}; } const auto poll = media->poll(); if (poll) { return poll->question.text; } return {}; } case MessageSubItem::PollOptions: { const auto media = data->media(); if (!media) { return {}; } const auto poll = media->poll(); if (!poll) { return {}; } QStringList options; for (const auto &answer : poll->answers) { auto line = answer.text.text; if (poll->totalVoters > 0 && answer.votes > 0) { const auto percent = (answer.votes * 100) / poll->totalVoters; line += u" ("_q + QString::number(percent) + u"%, "_q + QString::number(answer.votes) + u")"_q; } if (answer.chosen) { line += u" ✓"_q; } if (answer.correct) { line += u" ✔"_q; } options.push_back(line); } return options.join(u"; "_q); } case MessageSubItem::PollStatus: { const auto media = data->media(); if (!media) { return {}; } const auto poll = media->poll(); if (!poll) { return {}; } QStringList parts; parts.push_back(poll->quiz() ? tr::lng_polls_public_quiz(tr::now) : tr::lng_polls_public(tr::now)); if (poll->closed()) { parts.push_back( tr::lng_hours_closed(tr::now)); } parts.push_back(tr::lng_polls_votes_count( tr::now, lt_count, poll->totalVoters)); return parts.join(u", "_q); } case MessageSubItem::ContactName: { const auto media = data->media(); if (!media) { return {}; } const auto contact = media->sharedContact(); if (!contact) { return {}; } auto name = contact->firstName; if (!contact->lastName.isEmpty()) { if (!name.isEmpty()) { name += u" "_q; } name += contact->lastName; } return name; } case MessageSubItem::ContactPhone: { const auto media = data->media(); if (!media) { return {}; } const auto contact = media->sharedContact(); if (contact) { return contact->phoneNumber; } return {}; } case MessageSubItem::Location: { const auto media = data->media(); if (!media) { return {}; } if (media->location()) { return data->notificationText().text; } return {}; } case MessageSubItem::StickerEmoji: { const auto media = data->media(); if (!media) { return {}; } const auto document = media->document(); if (!document) { return {}; } if (const auto sticker = document->sticker()) { return sticker->alt; } return {}; } case MessageSubItem::GameTitle: { const auto media = data->media(); if (!media) { return {}; } const auto game = media->game(); if (game) { return game->title; } return {}; } case MessageSubItem::GameDescription: { const auto media = data->media(); if (!media) { return {}; } const auto game = media->game(); if (game) { return game->description; } return {}; } case MessageSubItem::InvoiceTitle: { const auto media = data->media(); if (!media) { return {}; } const auto invoice = media->invoice(); if (invoice) { return invoice->title; } return {}; } case MessageSubItem::InvoiceAmount: { const auto media = data->media(); if (!media) { return {}; } const auto invoice = media->invoice(); if (!invoice) { return {}; } auto result = invoice->currency + u" "_q + QString::number(invoice->amount / 100.0, 'f', 2); if (invoice->receiptMsgId) { result += u" ("_q + tr::lng_sr_message_invoice_paid(tr::now) + u")"_q; } else { result += u" ("_q + tr::lng_sr_message_invoice_unpaid(tr::now) + u")"_q; } return result; } case MessageSubItem::Spoiler: { const auto media = data->media(); if (media && media->hasSpoiler()) { return tr::lng_sr_message_spoiler(tr::now); } return {}; } case MessageSubItem::Dice: { const auto media = data->media(); if (!media) { return {}; } const auto notification = data->notificationText().text; if (media->game() || media->poll()) { return {}; } if (!media->document() && !media->photo() && !media->sharedContact() && !media->location() && !media->invoice() && !media->giveawayStart() && !media->giveawayResults() && !media->gift() && !media->todolist() && !media->game() && !media->poll() && !media->webpage() && !notification.isEmpty()) { return notification; } return {}; } case MessageSubItem::Giveaway: { const auto media = data->media(); if (!media) { return {}; } if (const auto giveaway = media->giveawayStart()) { QStringList parts; if (giveaway->quantity > 0) { parts.push_back(QString::number(giveaway->quantity) + u" winners"_q); } if (giveaway->months > 0) { parts.push_back(QString::number(giveaway->months) + u" months Premium"_q); } if (giveaway->credits > 0) { parts.push_back(QString::number(giveaway->credits) + u" stars"_q); } if (!giveaway->additionalPrize.isEmpty()) { parts.push_back(giveaway->additionalPrize); } return parts.join(u", "_q); } if (const auto results = media->giveawayResults()) { QStringList parts; parts.push_back(QString::number(results->winnersCount) + u" winners"_q); if (results->unclaimedCount > 0) { parts.push_back(QString::number(results->unclaimedCount) + u" unclaimed"_q); } if (results->refunded) { parts.push_back(u"refunded"_q); } return parts.join(u", "_q); } return {}; } case MessageSubItem::Gift: { const auto media = data->media(); if (!media) { return {}; } const auto gift = media->gift(); if (!gift) { return {}; } switch (gift->type) { case Data::GiftType::Premium: return tr::lng_sr_message_gift_premium( tr::now, lt_count, gift->count); case Data::GiftType::Credits: case Data::GiftType::StarGift: return tr::lng_sr_message_gift_credits( tr::now, lt_count, gift->count); default: if (!gift->giftTitle.isEmpty()) { return gift->giftTitle; } return {}; } } case MessageSubItem::TodoTitle: { const auto media = data->media(); if (!media) { return {}; } const auto todolist = media->todolist(); if (todolist) { return todolist->title.text; } return {}; } case MessageSubItem::TodoItems: { const auto media = data->media(); if (!media) { return {}; } const auto todolist = media->todolist(); if (!todolist) { return {}; } QStringList items; for (const auto &todoItem : todolist->items) { auto line = todoItem.text.text; line += u" ("_q; line += todoItem.completedBy ? tr::lng_sr_message_todo_completed(tr::now) : tr::lng_sr_message_todo_not_completed(tr::now); line += u")"_q; items.push_back(line); } return items.join(u"; "_q); } case MessageSubItem::Factcheck: { const auto text = data->factcheckText(); if (!text.empty()) { return text.text; } return {}; } case MessageSubItem::ForwardDate: { const auto fwd = data->Get(); if (!fwd) { return {}; } if (fwd->originalDate) { const auto dt = base::unixtime::parse(fwd->originalDate); return QLocale().toString(dt, QLocale::ShortFormat); } return {}; } case MessageSubItem::ForwardAuthor: { const auto fwd = data->Get(); if (!fwd) { return {}; } if (!fwd->originalPostAuthor.isEmpty()) { return fwd->originalPostAuthor; } if (fwd->imported) { return u"Imported"_q; } return {}; } case MessageSubItem::PaidReactions: { const auto &reactions = data->reactions(); for (const auto &reaction : reactions) { if (reaction.id.paid() && reaction.count > 0) { return QString::number(reaction.count); } } return {}; } case MessageSubItem::Count: break; } return {}; } std::vector ActiveMessageSubItems( not_null view, not_null history) { auto result = std::vector(); result.reserve(int(MessageSubItem::Count)); for (auto i = 0; i != int(MessageSubItem::Count); ++i) { const auto item = MessageSubItem(i); if (!MessageSubItemValue(view, history, item).isEmpty()) { result.push_back(item); } } return result; } } // namespace HistoryView