mirror of
https://github.com/vale981/tdesktop
synced 2025-03-05 17:51:41 -05:00
Allow to send scheduled messages instantly.
This commit is contained in:
parent
956bb876f6
commit
694f771131
17 changed files with 256 additions and 51 deletions
|
@ -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?";
|
||||
|
|
|
@ -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<Int, int32> || std::is_same_v<Int, uint32>>>
|
||||
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 <typename IntRange>
|
||||
inline int32 CountHash(IntRange &&range) {
|
||||
[[nodiscard]] inline int32 CountHash(IntRange &&range) {
|
||||
auto result = HashInit();
|
||||
for (const auto value : range) {
|
||||
HashUpdate(result, value);
|
||||
|
|
|
@ -78,13 +78,14 @@ ScheduledMessages::~ScheduledMessages() {
|
|||
}
|
||||
|
||||
MsgId ScheduledMessages::lookupId(not_null<HistoryItem*> 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*> history) const {
|
||||
|
|
|
@ -475,6 +475,10 @@ bool HistoryItem::canPin() const {
|
|||
return _history->peer->canPinMessages();
|
||||
}
|
||||
|
||||
bool HistoryItem::allowsSendNow() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HistoryItem::allowsForward() const {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -291,6 +291,95 @@ void AddForwardAction(
|
|||
AddForwardMessageAction(menu, request, list);
|
||||
}
|
||||
|
||||
bool AddSendNowSelectedAction(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
const ContextMenuRequest &request,
|
||||
not_null<ListWidget*> 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<HistoryItem*> 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<Ui::PopupMenu*> menu,
|
||||
const ContextMenuRequest &request,
|
||||
not_null<ListWidget*> 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<Ui::PopupMenu*> menu,
|
||||
const ContextMenuRequest &request,
|
||||
not_null<ListWidget*> list) {
|
||||
AddSendNowSelectedAction(menu, request, list);
|
||||
AddSendNowMessageAction(menu, request, list);
|
||||
}
|
||||
|
||||
bool AddDeleteSelectedAction(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
const ContextMenuRequest &request,
|
||||
|
@ -426,6 +515,7 @@ void AddMessageActions(
|
|||
not_null<ListWidget*> list) {
|
||||
AddPostLinkAction(menu, request);
|
||||
AddForwardAction(menu, request, list);
|
||||
AddSendNowAction(menu, request, list);
|
||||
AddDeleteAction(menu, request, list);
|
||||
AddSelectionAction(menu, request, list);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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<Element*> 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()) {
|
||||
|
|
|
@ -112,6 +112,7 @@ private:
|
|||
void updateScrollDownVisibility();
|
||||
void updateScrollDownPosition();
|
||||
|
||||
void confirmSendNowSelected();
|
||||
void confirmDeleteSelected();
|
||||
void clearSelected();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<Ui::RoundButton> _clear;
|
||||
object_ptr<Ui::RoundButton> _forward, _delete;
|
||||
object_ptr<Ui::RoundButton> _forward, _sendNow, _delete;
|
||||
|
||||
object_ptr<Ui::IconButton> _back;
|
||||
object_ptr<Ui::UnreadBadge> _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;
|
||||
|
||||
|
|
|
@ -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<DocumentData*> 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() {
|
||||
|
|
|
@ -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<Ui::RpWidget> ShowForwardMessagesBox(
|
|||
return weak->data();
|
||||
}
|
||||
|
||||
QPointer<Ui::RpWidget> ShowSendNowMessagesBox(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<History*> history,
|
||||
MessageIdsList &&items,
|
||||
FnMut<void()> &&successCallback) {
|
||||
const auto session = &navigation->session();
|
||||
const auto text = "Send now?";
|
||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||
auto done = [
|
||||
=,
|
||||
list = std::move(items),
|
||||
callback = std::move(successCallback)
|
||||
]() mutable {
|
||||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
}
|
||||
auto ids = QVector<MTPint>();
|
||||
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<MTPint>(ids)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
session->api().applyUpdates(result);
|
||||
}).send();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
*box = Ui::show(
|
||||
Box<ConfirmBox>(text, tr::lng_send_button(tr::now), std::move(done)),
|
||||
LayerOption::KeepOther);
|
||||
return box->data();
|
||||
}
|
||||
|
||||
void PeerMenuAddChannelMembers(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<ChannelData*> channel) {
|
||||
|
|
|
@ -74,4 +74,10 @@ QPointer<Ui::RpWidget> ShowForwardMessagesBox(
|
|||
MessageIdsList &&items,
|
||||
FnMut<void()> &&successCallback = nullptr);
|
||||
|
||||
QPointer<Ui::RpWidget> ShowSendNowMessagesBox(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<History*> history,
|
||||
MessageIdsList &&items,
|
||||
FnMut<void()> &&successCallback = nullptr);
|
||||
|
||||
} // namespace Window
|
||||
|
|
Loading…
Add table
Reference in a new issue