diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 3ec8e441e..3d5ff94b7 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1388,6 +1388,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_context_reply_msg" = "Reply"; "lng_context_edit_msg" = "Edit"; "lng_context_forward_msg" = "Forward Message"; +"lng_context_send_now_msg" = "Send now"; "lng_context_delete_msg" = "Delete Message"; "lng_context_select_msg" = "Select Message"; "lng_context_report_msg" = "Report Message"; @@ -1397,6 +1398,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_context_copy_selected" = "Copy Selected Text"; "lng_context_copy_selected_items" = "Copy Selected as Text"; "lng_context_forward_selected" = "Forward Selected"; +"lng_context_send_now_selected" = "Send selected now"; "lng_context_delete_selected" = "Delete Selected"; "lng_context_clear_selection" = "Clear Selection"; "lng_send_image_empty" = "Could not send an empty file: {name}"; @@ -1474,6 +1476,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_selected_clear" = "Cancel"; "lng_selected_delete" = "Delete"; "lng_selected_forward" = "Forward"; +"lng_selected_send_now" = "Send now"; "lng_selected_cancel_sure_this" = "Cancel uploading?"; "lng_selected_upload_stop" = "Stop"; "lng_selected_delete_sure_this" = "Do you want to delete this message?"; diff --git a/Telegram/SourceFiles/api/api_hash.h b/Telegram/SourceFiles/api/api_hash.h index e3ee9a570..ed760cb96 100644 --- a/Telegram/SourceFiles/api/api_hash.h +++ b/Telegram/SourceFiles/api/api_hash.h @@ -9,24 +9,29 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Api { -uint32 HashInit() { +[[nodiscard]] inline uint32 HashInit() { return 0; } -template < - typename Int, - typename = std::enable_if_t< - std::is_same_v || std::is_same_v>> -void HashUpdate(uint32 &already, Int value) { - already += (already * 20261) + uint32(value); +inline void HashUpdate(uint32 &already, uint32 value) { + already = (already * 20261) + uint32(value); } -int32 HashFinalize(uint32 already) { +inline void HashUpdate(uint32 &already, int32 value) { + HashUpdate(already, uint32(value)); +} + +inline void HashUpdate(uint32 &already, uint64 value) { + HashUpdate(already, uint32(value >> 32)); + HashUpdate(already, uint32(value & 0xFFFFFFFFULL)); +} + +[[nodiscard]] inline int32 HashFinalize(uint32 already) { return int32(already & 0x7FFFFFFF); } template -inline int32 CountHash(IntRange &&range) { +[[nodiscard]] inline int32 CountHash(IntRange &&range) { auto result = HashInit(); for (const auto value : range) { HashUpdate(result, value); diff --git a/Telegram/SourceFiles/data/data_scheduled_messages.cpp b/Telegram/SourceFiles/data/data_scheduled_messages.cpp index 4b1674491..d14fa898b 100644 --- a/Telegram/SourceFiles/data/data_scheduled_messages.cpp +++ b/Telegram/SourceFiles/data/data_scheduled_messages.cpp @@ -78,13 +78,14 @@ ScheduledMessages::~ScheduledMessages() { } MsgId ScheduledMessages::lookupId(not_null item) const { - if (const auto i = _data.find(item->history()); i != end(_data)) { - const auto &list = i->second.idByItem; - if (const auto j = list.find(item); j != end(list)) { - return j->second; - } - } - return MsgId(0); + Expects(item->isScheduled()); + + const auto i = _data.find(item->history()); + Assert(i != end(_data)); + const auto &list = i->second; + const auto j = list.idByItem.find(item); + Assert(j != end(list.idByItem)); + return j->second; } int ScheduledMessages::count(not_null history) const { diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 51456a5ab..fe3ba57b9 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -475,6 +475,10 @@ bool HistoryItem::canPin() const { return _history->peer->canPinMessages(); } +bool HistoryItem::allowsSendNow() const { + return false; +} + bool HistoryItem::allowsForward() const { return false; } diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 25f35f23a..6f95b9767 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -266,6 +266,7 @@ public: bool isPinned() const; bool canPin() const; bool canStopPoll() const; + virtual bool allowsSendNow() const; virtual bool allowsForward() const; virtual bool allowsEdit(TimeId now) const; bool canDelete() const; diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 6709c16e1..e3f93f774 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -742,6 +742,10 @@ bool HistoryMessage::allowsForward() const { return !_media || _media->allowsForward(); } +bool HistoryMessage::allowsSendNow() const { + return isScheduled(); +} + bool HistoryMessage::isTooOldForEdit(TimeId now) const { const auto peer = _history->peer; if (peer->isSelf()) { diff --git a/Telegram/SourceFiles/history/history_message.h b/Telegram/SourceFiles/history/history_message.h index ea2b91d58..d786fd6cf 100644 --- a/Telegram/SourceFiles/history/history_message.h +++ b/Telegram/SourceFiles/history/history_message.h @@ -108,6 +108,7 @@ public: const MTPMessageMedia &media); [[nodiscard]] bool allowsForward() const override; + [[nodiscard]] bool allowsSendNow() const override; [[nodiscard]] bool allowsEdit(TimeId now) const override; [[nodiscard]] bool uploading() const; diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 619660870..a3628861f 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -291,6 +291,95 @@ void AddForwardAction( AddForwardMessageAction(menu, request, list); } +bool AddSendNowSelectedAction( + not_null menu, + const ContextMenuRequest &request, + not_null list) { + if (!request.overSelection || request.selectedItems.empty()) { + return false; + } + if (ranges::find_if(request.selectedItems, [](const auto &item) { + return !item.canSendNow; + }) != end(request.selectedItems)) { + return false; + } + + const auto session = &request.navigation->session(); + auto histories = ranges::view::all( + request.selectedItems + ) | ranges::view::transform([&](const SelectedItem &item) { + return session->data().message(item.msgId); + }) | ranges::view::filter([](HistoryItem *item) { + return item != nullptr; + }) | ranges::view::transform([](not_null item) { + return item->history(); + }); + if (histories.begin() == histories.end()) { + return false; + } + const auto history = *histories.begin(); + + menu->addAction(tr::lng_context_send_now_selected(tr::now), [=] { + const auto weak = make_weak(list); + const auto callback = [=] { + request.navigation->showBackFromStack(); + }; + Window::ShowSendNowMessagesBox( + request.navigation, + history, + ExtractIdsList(request.selectedItems), + callback); + }); + return true; +} + +bool AddSendNowMessageAction( + not_null menu, + const ContextMenuRequest &request, + not_null list) { + const auto item = request.item; + if (!request.selectedItems.empty()) { + return false; + } else if (!item || !item->allowsSendNow()) { + return false; + } + const auto owner = &item->history()->owner(); + const auto asGroup = (request.pointState != PointState::GroupPart); + if (asGroup) { + if (const auto group = owner->groups().find(item)) { + if (ranges::find_if(group->items, [](auto item) { + return !item->allowsSendNow(); + }) != end(group->items)) { + return false; + } + } + } + const auto itemId = item->fullId(); + menu->addAction(tr::lng_context_send_now_msg(tr::now), [=] { + if (const auto item = owner->message(itemId)) { + const auto callback = [=] { + request.navigation->showBackFromStack(); + }; + Window::ShowSendNowMessagesBox( + request.navigation, + item->history(), + (asGroup + ? owner->itemOrItsGroup(item) + : MessageIdsList{ 1, itemId }), + callback); + } + }); + return true; +} + +void AddSendNowAction( + not_null menu, + const ContextMenuRequest &request, + not_null list) { + AddSendNowSelectedAction(menu, request, list); + AddSendNowMessageAction(menu, request, list); +} + bool AddDeleteSelectedAction( not_null menu, const ContextMenuRequest &request, @@ -426,6 +515,7 @@ void AddMessageActions( not_null list) { AddPostLinkAction(menu, request); AddForwardAction(menu, request, list); + AddSendNowAction(menu, request, list); AddDeleteAction(menu, request, list); AddSelectionAction(menu, request, list); } diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 52a5c74db..5f0bf9009 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -669,6 +669,7 @@ auto ListWidget::collectSelectedItems() const -> SelectedItems { auto result = SelectedItem(itemId); result.canDelete = selection.canDelete; result.canForward = selection.canForward; + result.canSendNow = selection.canSendNow; return result; }; auto items = SelectedItems(); @@ -770,6 +771,7 @@ bool ListWidget::addToSelection( } iterator->second.canDelete = item->canDelete(); iterator->second.canForward = item->allowsForward(); + iterator->second.canSendNow = item->allowsSendNow(); return true; } diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 209c20b25..d1687808d 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -46,6 +46,7 @@ struct SelectedItem { FullMsgId msgId; bool canDelete = false; bool canForward = false; + bool canSendNow = false; }; @@ -78,6 +79,7 @@ public: struct SelectionData { bool canDelete = false; bool canForward = false; + bool canSendNow = false; }; diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index db3d0ad82..348aaf957 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/special_buttons.h" #include "boxes/confirm_box.h" #include "window/window_session_controller.h" +#include "window/window_peer_menu.h" #include "core/event_filter.h" #include "main/main_session.h" #include "data/data_session.h" @@ -56,6 +57,10 @@ ScheduledWidget::ScheduledWidget( _topBar->resizeToWidth(width()); _topBar->show(); + _topBar->sendNowSelectionRequest( + ) | rpl::start_with_next([=] { + confirmSendNowSelected(); + }, _topBar->lifetime()); _topBar->deleteSelectionRequest( ) | rpl::start_with_next([=] { confirmDeleteSelected(); @@ -386,12 +391,12 @@ void ScheduledWidget::listSelectionChanged(SelectedItems &&items) { HistoryView::TopBarWidget::SelectedState state; state.count = items.size(); for (const auto item : items) { - if (item.canForward) { - ++state.canForwardCount; - } if (item.canDelete) { ++state.canDeleteCount; } + if (item.canSendNow) { + ++state.canSendNowCount; + } } _topBar->showSelected(state); } @@ -411,6 +416,19 @@ ClickHandlerPtr ScheduledWidget::listDateLink(not_null view) { return nullptr; } +void ScheduledWidget::confirmSendNowSelected() { + auto items = _inner->getSelectedItems(); + if (items.empty()) { + return; + } + const auto navigation = controller(); + Window::ShowSendNowMessagesBox( + navigation, + _history, + std::move(items), + [=] { navigation->showBackFromStack(); }); +} + void ScheduledWidget::confirmDeleteSelected() { auto items = _inner->getSelectedItems(); if (items.empty()) { diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h index ee8ae326c..2c672fdf1 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.h +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.h @@ -112,6 +112,7 @@ private: void updateScrollDownVisibility(); void updateScrollDownPosition(); + void confirmSendNowSelected(); void confirmDeleteSelected(); void clearSelected(); diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index 5af79e2ec..2c147db36 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -52,6 +52,7 @@ TopBarWidget::TopBarWidget( , _controller(controller) , _clear(this, tr::lng_selected_clear(), st::topBarClearButton) , _forward(this, tr::lng_selected_forward(), st::defaultActiveButton) +, _sendNow(this, tr::lng_selected_send_now(), st::defaultActiveButton) , _delete(this, tr::lng_selected_delete(), st::defaultActiveButton) , _back(this, st::historyTopBarBack) , _call(this, st::topBarCall) @@ -60,19 +61,21 @@ TopBarWidget::TopBarWidget( , _menuToggle(this, st::topBarMenuToggle) , _titlePeerText(st::windowMinWidth / 3) , _onlineUpdater([=] { updateOnlineDisplay(); }) { - subscribe(Lang::Current().updated(), [this] { refreshLang(); }); + subscribe(Lang::Current().updated(), [=] { refreshLang(); }); setAttribute(Qt::WA_OpaquePaintEvent); - _forward->setClickedCallback([this] { _forwardSelection.fire({}); }); - _forward->setWidthChangedCallback([this] { updateControlsGeometry(); }); - _delete->setClickedCallback([this] { _deleteSelection.fire({}); }); - _delete->setWidthChangedCallback([this] { updateControlsGeometry(); }); - _clear->setClickedCallback([this] { _clearSelection.fire({}); }); - _call->setClickedCallback([this] { onCall(); }); - _search->setClickedCallback([this] { onSearch(); }); - _menuToggle->setClickedCallback([this] { showMenu(); }); - _infoToggle->setClickedCallback([this] { toggleInfoSection(); }); - _back->addClickHandler([this] { backClicked(); }); + _forward->setClickedCallback([=] { _forwardSelection.fire({}); }); + _forward->setWidthChangedCallback([=] { updateControlsGeometry(); }); + _sendNow->setClickedCallback([=] { _sendNowSelection.fire({}); }); + _sendNow->setWidthChangedCallback([=] { updateControlsGeometry(); }); + _delete->setClickedCallback([=] { _deleteSelection.fire({}); }); + _delete->setWidthChangedCallback([=] { updateControlsGeometry(); }); + _clear->setClickedCallback([=] { _clearSelection.fire({}); }); + _call->setClickedCallback([=] { onCall(); }); + _search->setClickedCallback([=] { onSearch(); }); + _menuToggle->setClickedCallback([=] { showMenu(); }); + _infoToggle->setClickedCallback([=] { toggleInfoSection(); }); + _back->addClickHandler([=] { backClicked(); }); rpl::combine( _controller->activeChatValue(), @@ -522,12 +525,16 @@ void TopBarWidget::updateControlsGeometry() { auto selectedButtonsTop = countSelectedButtonsTop(_selectedShown.value(hasSelected ? 1. : 0.)); auto otherButtonsTop = selectedButtonsTop + st::topBarHeight; auto buttonsLeft = st::topBarActionSkip + (Adaptive::OneColumn() ? 0 : st::lineWidth); - auto buttonsWidth = _forward->contentWidth() + _delete->contentWidth() + _clear->width(); + auto buttonsWidth = (_forward->isHidden() ? 0 : _forward->contentWidth()) + + (_sendNow->isHidden() ? 0 : _sendNow->contentWidth()) + + (_delete->isHidden() ? 0 : _delete->contentWidth()) + + _clear->width(); buttonsWidth += buttonsLeft + st::topBarActionSkip * 3; auto widthLeft = qMin(width() - buttonsWidth, -2 * st::defaultActiveButton.width); auto buttonFullWidth = qMin(-(widthLeft / 2), 0); _forward->setFullWidth(buttonFullWidth); + _sendNow->setFullWidth(buttonFullWidth); _delete->setFullWidth(buttonFullWidth); selectedButtonsTop += (height() - _forward->height()) / 2; @@ -537,6 +544,11 @@ void TopBarWidget::updateControlsGeometry() { buttonsLeft += _forward->width() + st::topBarActionSkip; } + _sendNow->moveToLeft(buttonsLeft, selectedButtonsTop); + if (!_sendNow->isHidden()) { + buttonsLeft += _sendNow->width() + st::topBarActionSkip; + } + _delete->moveToLeft(buttonsLeft, selectedButtonsTop); _clear->moveToRight(st::topBarActionSkip, selectedButtonsTop); @@ -595,6 +607,7 @@ void TopBarWidget::updateControlsVisibility() { _clear->show(); _delete->setVisible(_canDelete); _forward->setVisible(_canForward); + _sendNow->setVisible(_canSendNow); auto backVisible = Adaptive::OneColumn() || (App::main() && !App::main()->stackIsEmpty()) @@ -665,29 +678,34 @@ void TopBarWidget::updateMembersShowArea() { void TopBarWidget::showSelected(SelectedState state) { auto canDelete = (state.count > 0 && state.count == state.canDeleteCount); auto canForward = (state.count > 0 && state.count == state.canForwardCount); - if (_selectedCount == state.count && _canDelete == canDelete && _canForward == canForward) { + auto canSendNow = (state.count > 0 && state.count == state.canSendNowCount); + if (_selectedCount == state.count && _canDelete == canDelete && _canForward == canForward && _canSendNow == canSendNow) { return; } if (state.count == 0) { // Don't change the visible buttons if the selection is cancelled. canDelete = _canDelete; canForward = _canForward; + canSendNow = _canSendNow; } auto wasSelected = (_selectedCount > 0); _selectedCount = state.count; if (_selectedCount > 0) { _forward->setNumbersText(_selectedCount); + _sendNow->setNumbersText(_selectedCount); _delete->setNumbersText(_selectedCount); if (!wasSelected) { _forward->finishNumbersAnimation(); + _sendNow->finishNumbersAnimation(); _delete->finishNumbersAnimation(); } } auto hasSelected = (_selectedCount > 0); - if (_canDelete != canDelete || _canForward != canForward) { + if (_canDelete != canDelete || _canForward != canForward || _canSendNow != canSendNow) { _canDelete = canDelete; _canForward = canForward; + _canSendNow = canSendNow; updateControlsVisibility(); } if (wasSelected != hasSelected) { diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.h b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.h index 0614e69e5..36bfd95ec 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.h @@ -38,6 +38,7 @@ public: int count = 0; int canDeleteCount = 0; int canForwardCount = 0; + int canSendNowCount = 0; }; enum class Section { History, @@ -64,6 +65,9 @@ public: rpl::producer<> forwardSelectionRequest() const { return _forwardSelection.events(); } + rpl::producer<> sendNowSelectionRequest() const { + return _sendNowSelection.events(); + } rpl::producer<> deleteSelectionRequest() const { return _deleteSelection.events(); } @@ -123,11 +127,12 @@ private: int _selectedCount = 0; bool _canDelete = false; bool _canForward = false; + bool _canSendNow = false; Ui::Animations::Simple _selectedShown; object_ptr _clear; - object_ptr _forward, _delete; + object_ptr _forward, _sendNow, _delete; object_ptr _back; object_ptr _unreadBadge = { nullptr }; @@ -153,6 +158,7 @@ private: base::Timer _onlineUpdater; rpl::event_stream<> _forwardSelection; + rpl::event_stream<> _sendNowSelection; rpl::event_stream<> _deleteSelection; rpl::event_stream<> _clearSelection; diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 9c5c6dae6..478747694 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/input_fields.h" #include "ui/emoji_config.h" #include "export/export_settings.h" +#include "api/api_hash.h" #include "core/crash_reports.h" #include "core/update_checker.h" #include "observer_peer.h" @@ -3854,13 +3855,11 @@ void readArchivedStickers() { } int32 countDocumentVectorHash(const QVector vector) { - uint32 acc = 0; - for_const (auto doc, vector) { - auto docId = doc->id; - acc = (acc * 20261) + uint32(docId >> 32); - acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF); + auto result = Api::HashInit(); + for (const auto document : vector) { + Api::HashUpdate(result, document->id); } - return int32(acc & 0x7FFFFFFF); + return Api::HashFinalize(result); } int32 countSpecialStickerSetHash(uint64 setId) { @@ -3873,7 +3872,7 @@ int32 countSpecialStickerSetHash(uint64 setId) { } int32 countStickersHash(bool checkOutdatedInfo) { - uint32 acc = 0; + auto result = Api::HashInit(); bool foundOutdated = false; auto &sets = Auth().data().stickerSets(); auto &order = Auth().data().stickerSetsOrder(); @@ -3884,11 +3883,13 @@ int32 countStickersHash(bool checkOutdatedInfo) { foundOutdated = true; } else if (!(j->flags & MTPDstickerSet_ClientFlag::f_special) && !(j->flags & MTPDstickerSet::Flag::f_archived)) { - acc = (acc * 20261) + j->hash; + Api::HashUpdate(result, j->hash); } } } - return (!checkOutdatedInfo || !foundOutdated) ? int32(acc & 0x7FFFFFFF) : 0; + return (!checkOutdatedInfo || !foundOutdated) + ? Api::HashFinalize(result) + : 0; } int32 countRecentStickersHash() { @@ -3900,19 +3901,18 @@ int32 countFavedStickersHash() { } int32 countFeaturedStickersHash() { - uint32 acc = 0; - auto &sets = Auth().data().stickerSets(); - auto &featured = Auth().data().featuredStickerSetsOrder(); - for_const (auto setId, featured) { - acc = (acc * 20261) + uint32(setId >> 32); - acc = (acc * 20261) + uint32(setId & 0xFFFFFFFF); + auto result = Api::HashInit(); + const auto &sets = Auth().data().stickerSets(); + const auto &featured = Auth().data().featuredStickerSetsOrder(); + for (const auto setId : featured) { + Api::HashUpdate(result, setId); auto it = sets.constFind(setId); if (it != sets.cend() && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) { - acc = (acc * 20261) + 1U; + Api::HashUpdate(result, 1); } } - return int32(acc & 0x7FFFFFFF); + return Api::HashFinalize(result); } int32 countSavedGifsHash() { diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index ef8746c85..444859388 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "observer_peer.h" #include "history/history.h" +#include "history/history_item.h" #include "window/window_session_controller.h" #include "window/window_controller.h" #include "support/support_helper.h" @@ -40,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat.h" #include "data/data_drafts.h" #include "data/data_user.h" +#include "data/data_scheduled_messages.h" #include "dialogs/dialogs_key.h" #include "boxes/peers/edit_peer_info_box.h" #include "styles/style_boxes.h" @@ -849,6 +851,47 @@ QPointer ShowForwardMessagesBox( return weak->data(); } +QPointer ShowSendNowMessagesBox( + not_null navigation, + not_null history, + MessageIdsList &&items, + FnMut &&successCallback) { + const auto session = &navigation->session(); + const auto text = "Send now?"; + const auto box = std::make_shared>(); + auto done = [ + =, + list = std::move(items), + callback = std::move(successCallback) + ]() mutable { + if (*box) { + (*box)->closeBox(); + } + auto ids = QVector(); + for (const auto &itemId : list) { + if (const auto item = session->data().message(itemId)) { + if (item->allowsSendNow()) { + ids.push_back(MTP_int( + session->data().scheduledMessages().lookupId(item))); + } + } + } + session->api().request(MTPmessages_SendScheduledMessages( + history->peer->input, + MTP_vector(ids) + )).done([=](const MTPUpdates &result) { + session->api().applyUpdates(result); + }).send(); + if (callback) { + callback(); + } + }; + *box = Ui::show( + Box(text, tr::lng_send_button(tr::now), std::move(done)), + LayerOption::KeepOther); + return box->data(); +} + void PeerMenuAddChannelMembers( not_null navigation, not_null channel) { diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h index 9133a340f..b376a4499 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.h +++ b/Telegram/SourceFiles/window/window_peer_menu.h @@ -74,4 +74,10 @@ QPointer ShowForwardMessagesBox( MessageIdsList &&items, FnMut &&successCallback = nullptr); +QPointer ShowSendNowMessagesBox( + not_null navigation, + not_null history, + MessageIdsList &&items, + FnMut &&successCallback = nullptr); + } // namespace Window