diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index bfd9e0bf3..6c7c4ac85 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3120,6 +3120,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "ktg_mute_for_selected_time" = "For selected time"; -"ktg_send_hide_via_message" = "Send without 'via @bot'"; +"ktg_send_preview" = "Send preview"; +"ktg_send_silent_preview" = "Send preview silent"; +"ktg_reminder_preview" = "Remind with preview"; +"ktg_schedule_preview" = "Send preview scheduled"; // Keys finished diff --git a/Telegram/Resources/langs/rewrites/en.json b/Telegram/Resources/langs/rewrites/en.json index f6d6f3a3a..8a9e07c38 100644 --- a/Telegram/Resources/langs/rewrites/en.json +++ b/Telegram/Resources/langs/rewrites/en.json @@ -223,6 +223,9 @@ "ktg_filters_hide_edit_toast": "Edit button is hidden.\nYou can enable it back in Kotatogram Settings.", "ktg_settings_telegram_sites_autologin": "Auto-login on Telegram sites", "ktg_mute_for_selected_time": "For selected time", - "ktg_send_hide_via_message": "Send without 'via @bot'", + "ktg_send_preview": "Send preview", + "ktg_send_silent_preview": "Send preview silent", + "ktg_reminder_preview": "Remind with preview", + "ktg_schedule_preview": "Send preview scheduled", "dummy_last_string": "" } diff --git a/Telegram/Resources/langs/rewrites/ru.json b/Telegram/Resources/langs/rewrites/ru.json index 46fef6a23..07407a5ca 100644 --- a/Telegram/Resources/langs/rewrites/ru.json +++ b/Telegram/Resources/langs/rewrites/ru.json @@ -223,6 +223,9 @@ "ktg_filters_hide_edit_toast": "Кнопка изменения скрыта.\nВы можете включить её обратно в настройках Kotatogram.", "ktg_settings_telegram_sites_autologin": "Авто-вход на сайты Telegram", "ktg_mute_for_selected_time": "На указанное время", - "ktg_send_hide_via_message": "Отправить без \"через @bot\"", + "ktg_send_preview": "Отправить превью", + "ktg_send_silent_preview": "Отправить превью тихо", + "ktg_reminder_preview": "Напомнить с помощью превью", + "ktg_schedule_preview": "Отправить превью позже", "dummy_last_string": "" } diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index ebd0be1c7..1997e4c4f 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -184,6 +184,26 @@ void SendExistingMedia( } // namespace +void SendWebDocument( + Api::MessageToSend &&message, + not_null document, + Fn doneCallback, + bool forwarding) { + const auto inputMedia = [=] { + return MTP_inputMediaDocumentExternal( + MTP_flags(0), + MTP_string(document->url()), + MTPint()); // ttl_seconds + }; + SendExistingMedia( + std::move(message), + document, + inputMedia, + document->stickerOrGifOrigin(), + (doneCallback ? std::move(doneCallback) : nullptr), + forwarding); +} + void SendExistingDocument( Api::MessageToSend &&message, not_null document, diff --git a/Telegram/SourceFiles/api/api_sending.h b/Telegram/SourceFiles/api/api_sending.h index 459b3063a..28a9431ee 100644 --- a/Telegram/SourceFiles/api/api_sending.h +++ b/Telegram/SourceFiles/api/api_sending.h @@ -25,6 +25,12 @@ namespace Api { struct MessageToSend; struct SendAction; +void SendWebDocument( + Api::MessageToSend &&message, + not_null document, + Fn doneCallback = nullptr, + bool forwarding = false); + void SendExistingDocument( Api::MessageToSend &&message, not_null document, diff --git a/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp b/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp index 08271abd6..c73a443aa 100644 --- a/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp +++ b/Telegram/SourceFiles/chat_helpers/send_context_menu.cpp @@ -65,6 +65,36 @@ FillMenuResult FillSendMenu( return FillMenuResult::Success; } +FillMenuResult FillSendPreviewMenu( + not_null menu, + Type type, + Fn defaultSend, + Fn silent, + Fn schedule) { + if (!defaultSend && !silent && !schedule) { + return FillMenuResult::None; + } + const auto now = type; + if (now == Type::Disabled) { + return FillMenuResult::None; + } + + if (defaultSend && now != Type::Scheduled && now != Type::ScheduledToUser) { + menu->addAction(tr::ktg_send_preview(tr::now), defaultSend); + } + if (silent && now != Type::Reminder) { + menu->addAction(tr::ktg_send_silent_preview(tr::now), silent); + } + if (schedule && now != Type::SilentOnly) { + menu->addAction( + (now == Type::Reminder + ? tr::ktg_reminder_preview(tr::now) + : tr::ktg_schedule_preview(tr::now)), + schedule); + } + return FillMenuResult::Success; +} + void SetupMenuAndShortcuts( not_null button, Fn type, diff --git a/Telegram/SourceFiles/chat_helpers/send_context_menu.h b/Telegram/SourceFiles/chat_helpers/send_context_menu.h index 11f9824b6..a7662ebcc 100644 --- a/Telegram/SourceFiles/chat_helpers/send_context_menu.h +++ b/Telegram/SourceFiles/chat_helpers/send_context_menu.h @@ -44,6 +44,13 @@ FillMenuResult FillSendMenu( Fn silent, Fn schedule); +FillMenuResult FillSendPreviewMenu( + not_null menu, + Type type, + Fn defaultSend, + Fn silent, + Fn schedule); + void SetupMenuAndShortcuts( not_null button, Fn type, diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index 75c8fb691..fd380c286 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -1225,6 +1225,10 @@ void DocumentData::refreshFileReference(const QByteArray &value) { _videoThumbnail.location.refreshFileReference(value); } +QString DocumentData::url() const { + return _url; +} + QString DocumentData::filename() const { return _filename; } diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h index 09d7ec121..5831a1261 100644 --- a/Telegram/SourceFiles/data/data_document.h +++ b/Telegram/SourceFiles/data/data_document.h @@ -220,6 +220,7 @@ public: // to (this) received from the server "same" document. void collectLocalData(not_null local); + [[nodiscard]] QString url() const; [[nodiscard]] QString filename() const; [[nodiscard]] QString mimeString() const; [[nodiscard]] bool hasMimeType(QLatin1String mime) const; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 223c3bda1..00e226423 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1037,7 +1037,20 @@ void HistoryWidget::initTabbedSelector() { selector->inlineResultChosen( ) | filter | rpl::start_with_next([=](Selector::InlineChosen data) { - sendInlineResult(data); + if (data.sendPreview) { + const auto request = data.result->openRequest(); + if (const auto photo = request.photo()) { + sendExistingPhoto(photo, data.options); + } else if (const auto document = request.document()) { + sendExistingDocument(document, data.options); + } + + addRecentBot(data.bot); + clearFieldText(); + saveCloudDraft(); + } else { + sendInlineResult(data); + } }, lifetime()); selector->contextMenuRequested( @@ -1416,6 +1429,17 @@ void HistoryWidget::applyInlineBotQuery(UserData *bot, const QString &query) { } else if (const auto document = request.document()) { controller()->openDocument(document, FullMsgId()); } + } else if (result.sendPreview) { + const auto request = result.result->openRequest(); + if (const auto photo = request.photo()) { + sendExistingPhoto(photo, result.options); + } else if (const auto document = request.document()) { + sendExistingDocument(document, result.options); + } + + addRecentBot(result.bot); + clearFieldText(); + saveCloudDraft(); } else { sendInlineResult(result); } @@ -5785,17 +5809,7 @@ void HistoryWidget::sendInlineResult(InlineBots::ResultSelected result) { _saveDraftStart = crl::now(); saveDraft(); - auto &bots = cRefRecentInlineBots(); - const auto index = bots.indexOf(result.bot); - if (index) { - if (index > 0) { - bots.removeAt(index); - } else if (bots.size() >= RecentInlineBotsLimit) { - bots.resize(RecentInlineBotsLimit - 1); - } - bots.push_front(result.bot); - session().local().writeRecentHashtagsAndBots(); - } + addRecentBot(result.bot); hideSelectorControlsAnimated(); @@ -6171,7 +6185,12 @@ bool HistoryWidget::sendExistingDocument( auto message = Api::MessageToSend(_history); message.action.options = std::move(options); message.action.replyTo = replyToId(); - Api::SendExistingDocument(std::move(message), document); + + if (document->hasRemoteLocation()) { + Api::SendExistingDocument(std::move(message), document); + } else { + Api::SendWebDocument(std::move(message), document); + } if (_fieldAutocomplete->stickersShown()) { clearFieldText(); @@ -6933,6 +6952,20 @@ void HistoryWidget::messageDataReceived(ChannelData *channel, MsgId msgId) { } } +void HistoryWidget::addRecentBot(not_null bot) { + auto &bots = cRefRecentInlineBots(); + const auto index = bots.indexOf(bot); + if (index) { + if (index > 0) { + bots.removeAt(index); + } else if (bots.size() >= RecentInlineBotsLimit) { + bots.resize(RecentInlineBotsLimit - 1); + } + bots.push_front(bot); + session().local().writeRecentHashtagsAndBots(); + } +} + void HistoryWidget::updateReplyEditText(not_null item) { _replyEditMsgText.setText( st::messageTextStyle, diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index b6ae70da0..8b8f88e83 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -378,6 +378,8 @@ private: void requestMessageData(MsgId msgId); void messageDataReceived(ChannelData *channel, MsgId msgId); + void addRecentBot(not_null bot); + void send(Api::SendOptions options); void sendWithModifiers(Qt::KeyboardModifiers modifiers); void sendSilent(); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.h b/Telegram/SourceFiles/inline_bots/inline_bot_result.h index 5d243f49d..d2b7a1ce3 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.h @@ -134,6 +134,7 @@ struct ResultSelected { Api::SendOptions options; // Open in OverlayWidget; bool open = false; + bool sendPreview = false; }; } // namespace InlineBots diff --git a/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp b/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp index a568ddc03..3e70d9c01 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp @@ -258,7 +258,8 @@ void Inner::selectInlineResult( int row, int column, Api::SendOptions options, - bool open) { + bool open, + bool sendPreview) { if (row >= _rows.size() || column >= _rows.at(row).items.size()) { return; } @@ -271,6 +272,7 @@ void Inner::selectInlineResult( .bot = _inlineBot, .options = std::move(options), .open = open, + .sendPreview = sendPreview, }); } } @@ -316,16 +318,29 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) { SendMenu::DefaultSilentCallback(send), SendMenu::DefaultScheduleCallback(this, type, send)); - _menu->addAction(tr::ktg_send_hide_via_message(tr::now), [=] { - send({ .hideVia = true }); - }); + const auto hideViaActions = [&] { + const auto sendPreview = [=](Api::SendOptions options) { + selectInlineResult(row, column, options, false, true); + }; + + SendMenu::FillSendPreviewMenu( + _menu, + type, + [=] { sendPreview({}); }, + SendMenu::DefaultSilentCallback(sendPreview), + SendMenu::DefaultScheduleCallback(this, type, sendPreview)); + }; auto item = _rows[row].items[column]; if (const auto previewDocument = item->getPreviewDocument()) { + hideViaActions(); + auto callback = [&](const QString &text, Fn &&done) { _menu->addAction(text, std::move(done)); }; ChatHelpers::AddGifAction(std::move(callback), previewDocument); + } else if (const auto previewPhoto = item->getPreviewPhoto()) { + hideViaActions(); } if (!_menu->empty()) { diff --git a/Telegram/SourceFiles/inline_bots/inline_results_inner.h b/Telegram/SourceFiles/inline_bots/inline_results_inner.h index e794935fe..f26b0c2e5 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_inner.h +++ b/Telegram/SourceFiles/inline_bots/inline_results_inner.h @@ -152,7 +152,8 @@ private: int row, int column, Api::SendOptions options, - bool open); + bool open, + bool sendPreview = false); not_null _controller; const std::unique_ptr _pathGradient;