diff --git a/Telegram/Resources/icons/inline_button_copy.png b/Telegram/Resources/icons/inline_button_copy.png new file mode 100644 index 000000000..50732e98f Binary files /dev/null and b/Telegram/Resources/icons/inline_button_copy.png differ diff --git a/Telegram/Resources/icons/inline_button_copy@2x.png b/Telegram/Resources/icons/inline_button_copy@2x.png new file mode 100644 index 000000000..0c843e25f Binary files /dev/null and b/Telegram/Resources/icons/inline_button_copy@2x.png differ diff --git a/Telegram/Resources/icons/inline_button_copy@3x.png b/Telegram/Resources/icons/inline_button_copy@3x.png new file mode 100644 index 000000000..f2b2fce5b Binary files /dev/null and b/Telegram/Resources/icons/inline_button_copy@3x.png differ diff --git a/Telegram/SourceFiles/api/api_bot.cpp b/Telegram/SourceFiles/api/api_bot.cpp index dc5cfabb8..5342cbd2e 100644 --- a/Telegram/SourceFiles/api/api_bot.cpp +++ b/Telegram/SourceFiles/api/api_bot.cpp @@ -39,6 +39,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/layers/generic_box.h" #include "ui/text/text_utilities.h" +#include +#include + namespace Api { namespace { @@ -503,11 +506,19 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) { bot->session().attachWebView().open({ .bot = bot, .context = { .controller = controller }, - .button = {.text = button->text, .url = button->data }, + .button = { .text = button->text, .url = button->data }, .source = InlineBots::WebViewSourceButton{ .simple = true }, }); } } break; + + case ButtonType::CopyText: { + const auto text = QString::fromUtf8(button->data); + if (!text.isEmpty()) { + QGuiApplication::clipboard()->setText(text); + controller->showToast(tr::lng_text_copied(tr::now)); + } + } break; } } diff --git a/Telegram/SourceFiles/api/api_media.cpp b/Telegram/SourceFiles/api/api_media.cpp index 46a5b7fa3..22fc37631 100644 --- a/Telegram/SourceFiles/api/api_media.cpp +++ b/Telegram/SourceFiles/api/api_media.cpp @@ -37,7 +37,8 @@ MTPVector ComposeSendingDocumentAttributes( MTP_int(dimensions.width()), MTP_int(dimensions.height()), MTPint(), // preload_prefix_size - MTPdouble())); // video_start_ts + MTPdouble(), // video_start_ts + MTPstring())); // video_codec } else { attributes.push_back(MTP_documentAttributeImageSize( MTP_int(dimensions.width()), diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index fd324adf7..a3003bab4 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -547,7 +547,7 @@ void SendConfirmedFile( MTP_flags(Flag::f_document | (file->spoiler ? Flag::f_spoiler : Flag())), file->document, - MTPDocument(), // alt_document + MTPVector(), // alt_documents MTPint()); } else if (file->type == SendMediaType::Audio) { const auto ttlSeconds = file->to.options.ttlSeconds; @@ -572,7 +572,7 @@ void SendConfirmedFile( | (isVoice ? Flag::f_voice : Flag()) | (ttlSeconds ? Flag::f_ttl_seconds : Flag())), file->document, - MTPDocument(), // alt_document + MTPVector(), // alt_documents MTP_int(ttlSeconds)); } else { Unexpected("Type in sendFilesConfirmed."); diff --git a/Telegram/SourceFiles/data/components/sponsored_messages.cpp b/Telegram/SourceFiles/data/components/sponsored_messages.cpp index 3aeb2058c..3742fbc86 100644 --- a/Telegram/SourceFiles/data/components/sponsored_messages.cpp +++ b/Telegram/SourceFiles/data/components/sponsored_messages.cpp @@ -441,7 +441,9 @@ void SponsoredMessages::clicked(const FullMsgId &fullId) { const auto randomId = entryPtr->sponsored.randomId; const auto channel = entryPtr->item->history()->peer->asChannel(); Assert(channel != nullptr); + using Flag = MTPchannels_ClickSponsoredMessage::Flag; _session->api().request(MTPchannels_ClickSponsoredMessage( + MTP_flags(Flag(0)), channel->inputChannel, MTP_bytes(randomId) )).send(); diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index ef7f25e51..5f95e671b 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -148,6 +148,12 @@ std::vector> ButtonRowsFromTL( qs(data.vtext()), data.vurl().v }); + }, [&](const MTPDkeyboardButtonCopy &data) { + row.push_back({ + Type::CopyText, + qs(data.vtext()), + data.vcopy_text().v, + }); }, [&](const MTPDinputKeyboardButtonRequestPeer &data) { }); } @@ -181,6 +187,7 @@ QByteArray HistoryMessageMarkupButton::TypeToString( case Type::UserProfile: return "user_profile"; case Type::WebView: return "web_view"; case Type::SimpleWebView: return "simple_web_view"; + case Type::CopyText: return "copy_text"; } Unexpected("Type in HistoryMessageMarkupButton::Type."); } diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h index 7adf63d8c..ce2d97842 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.h +++ b/Telegram/SourceFiles/export/data/export_data_types.h @@ -745,6 +745,7 @@ struct HistoryMessageMarkupButton { UserProfile, WebView, SimpleWebView, + CopyText, }; static QByteArray TypeToString(const HistoryMessageMarkupButton &); diff --git a/Telegram/SourceFiles/history/history_item_reply_markup.cpp b/Telegram/SourceFiles/history/history_item_reply_markup.cpp index a24058683..5cd532ad5 100644 --- a/Telegram/SourceFiles/history/history_item_reply_markup.cpp +++ b/Telegram/SourceFiles/history/history_item_reply_markup.cpp @@ -209,6 +209,11 @@ void HistoryMessageMarkupData::fillRows( Type::SimpleWebView, qs(data.vtext()), data.vurl().v); + }, [&](const MTPDkeyboardButtonCopy &data) { + row.emplace_back( + Type::CopyText, + qs(data.vtext()), + data.vcopy_text().v); }, [&](const MTPDinputKeyboardButtonRequestPeer &data) { LOG(("API Error: inputKeyboardButtonRequestPeer.")); // Should not get those for the users. diff --git a/Telegram/SourceFiles/history/history_item_reply_markup.h b/Telegram/SourceFiles/history/history_item_reply_markup.h index 5ed8dc4a3..8d1d4e937 100644 --- a/Telegram/SourceFiles/history/history_item_reply_markup.h +++ b/Telegram/SourceFiles/history/history_item_reply_markup.h @@ -77,6 +77,7 @@ struct HistoryMessageMarkupButton { UserProfile, WebView, SimpleWebView, + CopyText, }; HistoryMessageMarkupButton( diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 09f3cd381..b8c22a68d 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -238,6 +238,7 @@ void KeyboardStyle::paintButtonIcon( case Type::SwitchInline: return &st->msgBotKbSwitchPmIcon(); case Type::WebView: case Type::SimpleWebView: return &st->msgBotKbWebviewIcon(); + case Type::CopyText: return &st->msgBotKbCopyIcon(); } return nullptr; }(); @@ -334,6 +335,7 @@ int KeyboardStyle::minButtonWidth( case Type::Game: iconWidth = st::historySendingInvertedIcon.width(); break; case Type::WebView: case Type::SimpleWebView: iconWidth = st::msgBotKbWebviewIcon.width(); break; + case Type::CopyText: return st::msgBotKbCopyIcon.width(); break; } if (iconWidth > 0) { result = std::max(result, 2 * iconWidth + 4 * int(st::msgBotKbIconPadding)); diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index 5db596997..39865d48e 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -124,7 +124,7 @@ messageMediaPhoto#695150d7 flags:# spoiler:flags.3?true photo:flags.0?Photo ttl_ messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia; messageMediaContact#70322949 phone_number:string first_name:string last_name:string vcard:string user_id:long = MessageMedia; messageMediaUnsupported#9f84f49e = MessageMedia; -messageMediaDocument#4cf4d72d flags:# nopremium:flags.3?true spoiler:flags.4?true video:flags.6?true round:flags.7?true voice:flags.8?true document:flags.0?Document alt_document:flags.5?Document ttl_seconds:flags.2?int = MessageMedia; +messageMediaDocument#dd570bd5 flags:# nopremium:flags.3?true spoiler:flags.4?true video:flags.6?true round:flags.7?true voice:flags.8?true document:flags.0?Document alt_documents:flags.5?Vector ttl_seconds:flags.2?int = MessageMedia; messageMediaWebPage#ddf10c3b flags:# force_large_media:flags.0?true force_small_media:flags.1?true manual:flags.3?true safe:flags.4?true webpage:WebPage = MessageMedia; messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia; messageMediaGame#fdb19008 game:Game = MessageMedia; @@ -573,7 +573,7 @@ accountDaysTTL#b8d0afdf days:int = AccountDaysTTL; documentAttributeImageSize#6c37c15c w:int h:int = DocumentAttribute; documentAttributeAnimated#11b58939 = DocumentAttribute; documentAttributeSticker#6319d612 flags:# mask:flags.1?true alt:string stickerset:InputStickerSet mask_coords:flags.0?MaskCoords = DocumentAttribute; -documentAttributeVideo#17399fad flags:# round_message:flags.0?true supports_streaming:flags.1?true nosound:flags.3?true duration:double w:int h:int preload_prefix_size:flags.2?int video_start_ts:flags.4?double = DocumentAttribute; +documentAttributeVideo#43c57c48 flags:# round_message:flags.0?true supports_streaming:flags.1?true nosound:flags.3?true duration:double w:int h:int preload_prefix_size:flags.2?int video_start_ts:flags.4?double video_codec:flags.5?string = DocumentAttribute; documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute; documentAttributeFilename#15590068 file_name:string = DocumentAttribute; documentAttributeHasStickers#9801d2f7 = DocumentAttribute; @@ -653,6 +653,7 @@ keyboardButtonWebView#13767230 text:string url:string = KeyboardButton; keyboardButtonSimpleWebView#a0c0505c text:string url:string = KeyboardButton; keyboardButtonRequestPeer#53d7bfd8 text:string button_id:int peer_type:RequestPeerType max_quantity:int = KeyboardButton; inputKeyboardButtonRequestPeer#c9662d05 flags:# name_requested:flags.0?true username_requested:flags.1?true photo_requested:flags.2?true text:string button_id:int peer_type:RequestPeerType max_quantity:int = KeyboardButton; +keyboardButtonCopy#75d2698e text:string copy_text:string = KeyboardButton; keyboardButtonRow#77608b83 buttons:Vector = KeyboardButtonRow; @@ -2358,7 +2359,7 @@ channels.reorderPinnedForumTopics#2950a18f flags:# force:flags.0?true channel:In channels.toggleAntiSpam#68f3e4eb channel:InputChannel enabled:Bool = Updates; channels.reportAntiSpamFalsePositive#a850a693 channel:InputChannel msg_id:int = Bool; channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates; -channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool; +channels.clickSponsoredMessage#1445d75 flags:# media:flags.0?true fullscreen:flags.1?true channel:InputChannel random_id:bytes = Bool; channels.updateColor#d8aa3671 flags:# for_profile:flags.1?true channel:InputChannel color:flags.2?int background_emoji_id:flags.0?long = Updates; channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates; channels.getChannelRecommendations#25a71742 flags:# channel:flags.0?InputChannel = messages.Chats; @@ -2542,4 +2543,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool; fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo; -// LAYER 187 +// LAYER 188 diff --git a/Telegram/SourceFiles/storage/localimageloader.cpp b/Telegram/SourceFiles/storage/localimageloader.cpp index dc3751b75..79c4af401 100644 --- a/Telegram/SourceFiles/storage/localimageloader.cpp +++ b/Telegram/SourceFiles/storage/localimageloader.cpp @@ -846,7 +846,8 @@ void FileLoadTask::process(Args &&args) { MTP_int(coverWidth), MTP_int(coverHeight), MTPint(), // preload_prefix_size - MTPdouble())); // video_start_ts + MTPdouble(), // video_start_ts + MTPstring())); // video_codec if (args.generateGoodThumbnail) { goodThumbnail = video->thumbnail; diff --git a/Telegram/SourceFiles/storage/serialize_document.cpp b/Telegram/SourceFiles/storage/serialize_document.cpp index efb527506..e13a587cf 100644 --- a/Telegram/SourceFiles/storage/serialize_document.cpp +++ b/Telegram/SourceFiles/storage/serialize_document.cpp @@ -208,7 +208,8 @@ DocumentData *Document::readFromStreamHelper( MTP_int(width), MTP_int(height), MTPint(), // preload_prefix_size - MTPdouble())); // video_start_ts + MTPdouble(), // video_start_ts + MTPstring())); // video_codec } else { attributes.push_back(MTP_documentAttributeImageSize( MTP_int(width), diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 724a4f789..3369b5fb2 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -330,6 +330,7 @@ msgBotKbUrlIcon: icon {{ "inline_button_url", msgBotKbIconFg }}; msgBotKbSwitchPmIcon: icon {{ "inline_button_switch", msgBotKbIconFg }}; msgBotKbPaymentIcon: icon {{ "inline_button_card", msgBotKbIconFg }}; msgBotKbWebviewIcon: icon {{ "inline_button_web", msgBotKbIconFg }}; +msgBotKbCopyIcon: icon {{ "inline_button_copy", msgBotKbIconFg }}; msgBotKbButton: BotKeyboardButton { margin: 2px; padding: 10px; diff --git a/Telegram/SourceFiles/ui/chat/chat_style.cpp b/Telegram/SourceFiles/ui/chat/chat_style.cpp index 0c50f77b8..a18889258 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_style.cpp @@ -187,6 +187,7 @@ ChatStyle::ChatStyle(rpl::producer colorIndices) { make(_msgBotKbPaymentIcon, st::msgBotKbPaymentIcon); make(_msgBotKbSwitchPmIcon, st::msgBotKbSwitchPmIcon); make(_msgBotKbWebviewIcon, st::msgBotKbWebviewIcon); + make(_msgBotKbCopyIcon, st::msgBotKbCopyIcon); make(_historyFastCommentsIcon, st::historyFastCommentsIcon); make(_historyFastShareIcon, st::historyFastShareIcon); make(_historyFastTranscribeIcon, st::historyFastTranscribeIcon); diff --git a/Telegram/SourceFiles/ui/chat/chat_style.h b/Telegram/SourceFiles/ui/chat/chat_style.h index b66cf814b..6247d3879 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.h +++ b/Telegram/SourceFiles/ui/chat/chat_style.h @@ -393,6 +393,9 @@ public: [[nodiscard]] const style::icon &msgBotKbWebviewIcon() const { return _msgBotKbWebviewIcon; } + [[nodiscard]] const style::icon &msgBotKbCopyIcon() const { + return _msgBotKbCopyIcon; + } [[nodiscard]] const style::icon &historyFastCommentsIcon() const { return _historyFastCommentsIcon; } @@ -535,6 +538,7 @@ private: style::icon _msgBotKbPaymentIcon = { Qt::Uninitialized }; style::icon _msgBotKbSwitchPmIcon = { Qt::Uninitialized }; style::icon _msgBotKbWebviewIcon = { Qt::Uninitialized }; + style::icon _msgBotKbCopyIcon = { Qt::Uninitialized }; style::icon _historyFastCommentsIcon = { Qt::Uninitialized }; style::icon _historyFastShareIcon = { Qt::Uninitialized }; style::icon _historyFastMoreIcon = { Qt::Uninitialized };