diff --git a/Telegram/Resources/langs/rewrites/en.json b/Telegram/Resources/langs/rewrites/en.json index cd8644a7b..b284b4396 100644 --- a/Telegram/Resources/langs/rewrites/en.json +++ b/Telegram/Resources/langs/rewrites/en.json @@ -169,6 +169,10 @@ "ktg_filters_hide_all_chats_toast": "\"All Chats\" folder is hidden.\nYou can enable it back in Kotatogram Settings.", "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_send_preview": "Send preview", + "ktg_send_silent_preview": "Send preview silent", + "ktg_reminder_preview": "Remind with preview", + "ktg_schedule_preview": "Send preview scheduled", "ktg_forward_sender_names_and_captions_removed": "Sender names and captions removed", "ktg_forward_remember_mode": "Remember forward mode", "ktg_forward_mode": "Forward mode", diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index a0b14583d..b1631d22a 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -1189,7 +1189,20 @@ void HistoryWidget::initTabbedSelector() { } return (data.recipientOverride == _peer); }) | rpl::start_with_next([=](ChatHelpers::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( @@ -1563,6 +1576,17 @@ void HistoryWidget::applyInlineBotQuery(UserData *bot, const QString &query) { } else if (const auto document = request.document()) { controller()->openDocument(document, {}, {}); } + } 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); } @@ -6552,17 +6576,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(); @@ -7904,6 +7918,20 @@ void HistoryWidget::messageDataReceived( } } +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) { const auto context = Core::MarkedTextContext{ .session = &session(), diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 05535711c..34c4023bf 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -376,6 +376,8 @@ private: void requestMessageData(MsgId msgId); void messageDataReceived(not_null peer, MsgId msgId); + void addRecentBot(not_null bot); + [[nodiscard]] Api::SendAction prepareSendAction( Api::SendOptions options) const; void send(Api::SendOptions options); diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 22145b376..864874e7a 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -68,6 +68,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session_settings.h" #include "mainwidget.h" #include "data/data_session.h" +#include "data/data_document.h" #include "data/data_user.h" #include "data/data_chat.h" #include "data/data_channel.h" @@ -787,7 +788,20 @@ void RepliesWidget::setupComposeControls() { controller()->sendingAnimation().appendSending( chosen.messageSendingFrom); const auto localId = chosen.messageSendingFrom.localId; - sendInlineResult(chosen.result, chosen.bot, chosen.options, localId); + if (chosen.sendPreview) { + const auto request = chosen.result->openRequest(); + if (const auto photo = request.photo()) { + sendExistingPhoto(photo, chosen.options); + } else if (const auto document = request.document()) { + sendExistingDocument(document, chosen.options, localId); + } + + addRecentBot(chosen.bot); + _composeControls->clear(); + finishSending(); + } else { + sendInlineResult(chosen.result, chosen.bot, chosen.options, localId); + } }, lifetime()); _composeControls->scrollRequests( @@ -1131,6 +1145,20 @@ bool RepliesWidget::showSendingFilesError( return true; } +void RepliesWidget::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); + bot->session().local().writeRecentHashtagsAndBots(); + } +} + Api::SendAction RepliesWidget::prepareSendAction( Api::SendOptions options) const { auto result = Api::SendAction(_history, options); @@ -1357,10 +1385,17 @@ bool RepliesWidget::sendExistingDocument( return false; } - Api::SendExistingDocument( - Api::MessageToSend(prepareSendAction(options)), - document, - localId); + if (document->hasRemoteLocation()) { + Api::SendExistingDocument( + Api::MessageToSend(prepareSendAction(options)), + document, + localId); + } else { + Api::SendWebDocument( + Api::MessageToSend(prepareSendAction(options)), + document, + localId); + } _composeControls->cancelReplyMessage(); finishSending(); @@ -1431,17 +1466,7 @@ void RepliesWidget::sendInlineResult( //_saveDraftStart = crl::now(); //onDraftSave(); - 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); - bot->session().local().writeRecentHashtagsAndBots(); - } + addRecentBot(bot); finishSending(); } diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.h b/Telegram/SourceFiles/history/view/history_view_replies_section.h index a8645a5c5..408a77dda 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.h +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.h @@ -231,6 +231,8 @@ private: void clearSelected(); void setPinnedVisibility(bool shown); + void addRecentBot(not_null bot); + [[nodiscard]] Api::SendAction prepareSendAction( Api::SendOptions options) const; void send(); diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 85ce03471..fcc2a33c5 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -284,7 +284,21 @@ void ScheduledWidget::setupComposeControls() { _composeControls->inlineResultChosen( ) | rpl::start_with_next([=](ChatHelpers::InlineChosen chosen) { - sendInlineResult(chosen.result, chosen.bot); + if (chosen.sendPreview) { + const auto request = chosen.result->openRequest(); + if (const auto photo = request.photo()) { + sendExistingPhoto(photo); + } else if (const auto document = request.document()) { + sendExistingDocument(document); + } + + addRecentBot(chosen.bot); + _composeControls->clear(); + _composeControls->hidePanelsAnimated(); + _composeControls->focus(); + } else { + sendInlineResult(chosen.result, chosen.bot); + } }, lifetime()); _composeControls->scrollRequests( @@ -567,6 +581,20 @@ bool ScheduledWidget::showSendingFilesError( return true; } +void ScheduledWidget::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); + bot->session().local().writeRecentHashtagsAndBots(); + } +} + Api::SendAction ScheduledWidget::prepareSendAction( Api::SendOptions options) const { auto result = Api::SendAction(_history, options); @@ -800,17 +828,7 @@ void ScheduledWidget::sendInlineResult( //_saveDraftStart = crl::now(); //onDraftSave(); - 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); - bot->session().local().writeRecentHashtagsAndBots(); - } + addRecentBot(bot); _composeControls->hidePanelsAnimated(); _composeControls->focus(); diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h index acbec32d8..05e7fa3d0 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h @@ -192,6 +192,8 @@ private: void confirmDeleteSelected(); void clearSelected(); + void addRecentBot(not_null bot); + [[nodiscard]] Api::SendAction prepareSendAction( Api::SendOptions options) const; void send(); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.h b/Telegram/SourceFiles/inline_bots/inline_bot_result.h index 45c8f6b39..81701f3ae 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.h @@ -137,6 +137,7 @@ struct ResultSelected { Ui::MessageSendingAnimationFrom messageSendingFrom; // 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 0103789ec..f3523a3dd 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_inner.cpp @@ -262,7 +262,8 @@ void Inner::mouseReleaseEvent(QMouseEvent *e) { void Inner::selectInlineResult( int index, Api::SendOptions options, - bool open) { + bool open, + bool sendPreview) { const auto item = _mosaic.maybeItemAt(index); if (!item) { return; @@ -301,6 +302,7 @@ void Inner::selectInlineResult( .options = std::move(options), .messageSendingFrom = messageSendingFrom(), .open = open, + .sendPreview = sendPreview, }); } } @@ -347,8 +349,23 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) { SendMenu::DefaultScheduleCallback(this, type, send), SendMenu::DefaultWhenOnlineCallback(send)); + const auto hideViaActions = [&] { + const auto sendPreview = [=, selected = _selected](Api::SendOptions options) { + selectInlineResult(selected, options, false, true); + }; + + SendMenu::FillSendPreviewMenu( + _menu, + type, + [=] { sendPreview({}); }, + SendMenu::DefaultSilentCallback(sendPreview), + SendMenu::DefaultScheduleCallback(this, type, sendPreview)); + }; + const auto item = _mosaic.itemAt(_selected); if (const auto previewDocument = item->getPreviewDocument()) { + hideViaActions(); + auto callback = [&]( const QString &text, Fn &&done, @@ -359,6 +376,8 @@ void Inner::contextMenuEvent(QContextMenuEvent *e) { std::move(callback), _controller->uiShow(), 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 5aa22578a..56725360a 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_inner.h +++ b/Telegram/SourceFiles/inline_bots/inline_results_inner.h @@ -142,7 +142,8 @@ private: void selectInlineResult( int index, Api::SendOptions options, - bool open); + bool open, + bool sendPreview = false); not_null _controller; const std::unique_ptr _pathGradient; diff --git a/Telegram/SourceFiles/menu/menu_send.cpp b/Telegram/SourceFiles/menu/menu_send.cpp index 2d5ca3194..8c430a965 100644 --- a/Telegram/SourceFiles/menu/menu_send.cpp +++ b/Telegram/SourceFiles/menu/menu_send.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "menu/menu_send.h" +#include "kotato/kotato_lang.h" #include "api/api_common.h" #include "base/event_filter.h" #include "boxes/abstract_box.h" @@ -62,6 +63,7 @@ FillMenuResult FillSendMenu( } const auto now = type; if (now == Type::Disabled + || now == Type::PreviewOnly || (!silent && now == Type::SilentOnly)) { return FillMenuResult::None; } @@ -89,6 +91,38 @@ 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) { + menu->addAction(ktr("ktg_send_preview"), defaultSend); + } + if (type != Type::PreviewOnly) { + if (silent && now != Type::Reminder) { + menu->addAction(ktr("ktg_send_silent_preview"), silent); + } + if (schedule && now != Type::SilentOnly) { + menu->addAction( + (now == Type::Reminder + ? ktr("ktg_reminder_preview") + : ktr("ktg_schedule_preview")), + schedule); + } + } + return FillMenuResult::Success; +} + void SetupMenuAndShortcuts( not_null button, Fn type, @@ -125,6 +159,7 @@ void SetupMenuAndShortcuts( const auto now = type(); if (now == Type::Disabled + || now == Type::PreviewOnly || (!silent && now == Type::SilentOnly)) { return; } diff --git a/Telegram/SourceFiles/menu/menu_send.h b/Telegram/SourceFiles/menu/menu_send.h index 0676de49e..6f91487dd 100644 --- a/Telegram/SourceFiles/menu/menu_send.h +++ b/Telegram/SourceFiles/menu/menu_send.h @@ -28,6 +28,7 @@ enum class Type { Scheduled, ScheduledToUser, // For "Send when online". Reminder, + PreviewOnly, }; enum class FillMenuResult { @@ -49,6 +50,13 @@ FillMenuResult FillSendMenu( Fn schedule, Fn whenOnline); +FillMenuResult FillSendPreviewMenu( + not_null menu, + Type type, + Fn defaultSend, + Fn silent, + Fn schedule); + void SetupMenuAndShortcuts( not_null button, Fn type,