Allow to schedule created polls.

This commit is contained in:
John Preston 2019-08-20 16:21:10 +03:00
parent 8eac2dcb78
commit ef7087348a
17 changed files with 243 additions and 115 deletions

View File

@ -16,6 +16,11 @@ struct SendOptions {
bool removeWebPageId = false; bool removeWebPageId = false;
}; };
enum class SendType {
Normal,
Scheduled,
};
struct SendAction { struct SendAction {
explicit SendAction(not_null<History*> history) : history(history) { explicit SendAction(not_null<History*> history) : history(history) {
} }

View File

@ -19,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "core/event_filter.h" #include "core/event_filter.h"
#include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/emoji_suggestions_widget.h"
#include "chat_helpers/message_field.h"
#include "history/view/history_view_schedule_box.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "base/unique_qptr.h" #include "base/unique_qptr.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -592,11 +594,15 @@ void Options::checkLastOption() {
} // namespace } // namespace
CreatePollBox::CreatePollBox(QWidget*, not_null<Main::Session*> session) CreatePollBox::CreatePollBox(
: _session(session) { QWidget*,
not_null<Main::Session*> session,
Api::SendType sendType)
: _session(session)
, _sendType(sendType) {
} }
rpl::producer<PollData> CreatePollBox::submitRequests() const { rpl::producer<CreatePollBox::Result> CreatePollBox::submitRequests() const {
return _submitRequests.events(); return _submitRequests.events();
} }
@ -703,6 +709,19 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
result.answers = options->toPollAnswers(); result.answers = options->toPollAnswers();
return result; return result;
}; };
const auto send = [=](Api::SendOptions options) {
_submitRequests.fire({ collectResult(), options });
};
const auto sendSilent = [=] {
auto options = Api::SendOptions();
options.silent = true;
send(options);
};
const auto sendScheduled = [=] {
Ui::show(
HistoryView::PrepareScheduleBox(this, send),
LayerOption::KeepOther);
};
const auto updateValid = [=] { const auto updateValid = [=] {
valid->fire(isValidQuestion() && options->isValid()); valid->fire(isValidQuestion() && options->isValid());
}; };
@ -715,9 +734,16 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
) | rpl::start_with_next([=](bool valid) { ) | rpl::start_with_next([=](bool valid) {
clearButtons(); clearButtons();
if (valid) { if (valid) {
addButton( const auto submit = addButton(
tr::lng_polls_create_button(), tr::lng_polls_create_button(),
[=] { _submitRequests.fire(collectResult()); }); [=] { send({}); });
if (_sendType == Api::SendType::Normal) {
SetupSendMenu(
submit.data(),
[=] { return true; },
sendSilent,
sendScheduled);
}
} }
addButton(tr::lng_cancel(), [=] { closeBox(); }); addButton(tr::lng_cancel(), [=] { closeBox(); });
}, lifetime()); }, lifetime());

View File

@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "api/api_common.h"
#include "data/data_poll.h"
struct PollData; struct PollData;
@ -21,9 +23,17 @@ class Session;
class CreatePollBox : public BoxContent { class CreatePollBox : public BoxContent {
public: public:
CreatePollBox(QWidget*, not_null<Main::Session*> session); struct Result {
PollData poll;
Api::SendOptions options;
};
rpl::producer<PollData> submitRequests() const; CreatePollBox(
QWidget*,
not_null<Main::Session*> session,
Api::SendType sendType);
rpl::producer<Result> submitRequests() const;
void submitFailed(const QString &error); void submitFailed(const QString &error);
void setInnerFocus() override; void setInnerFocus() override;
@ -37,8 +47,9 @@ private:
not_null<Ui::VerticalLayout*> container); not_null<Ui::VerticalLayout*> container);
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
const Api::SendType _sendType = Api::SendType();
Fn<void()> _setInnerFocus; Fn<void()> _setInnerFocus;
Fn<rpl::producer<bool>()> _dataIsValidValue; Fn<rpl::producer<bool>()> _dataIsValidValue;
rpl::event_stream<PollData> _submitRequests; rpl::event_stream<Result> _submitRequests;
}; };

View File

@ -1368,8 +1368,10 @@ SendFilesBox::SendFilesBox(
Storage::PreparedList &&list, Storage::PreparedList &&list,
const TextWithTags &caption, const TextWithTags &caption,
CompressConfirm compressed, CompressConfirm compressed,
SendLimit limit) SendLimit limit,
Api::SendType sendType)
: _controller(controller) : _controller(controller)
, _sendType(sendType)
, _list(std::move(list)) , _list(std::move(list))
, _compressConfirmInitial(compressed) , _compressConfirmInitial(compressed)
, _compressConfirm(compressed) , _compressConfirm(compressed)
@ -1471,11 +1473,13 @@ void SendFilesBox::setupShadows(
void SendFilesBox::prepare() { void SendFilesBox::prepare() {
_send = addButton(tr::lng_send_button(), [=] { send({}); }); _send = addButton(tr::lng_send_button(), [=] { send({}); });
SetupSendWithoutSound( if (_sendType == Api::SendType::Normal) {
_send, SetupSendMenu(
[=] { return true; }, _send,
[=] { sendSilent(); }, [=] { return true; },
[=] { sendScheduled(); }); [=] { sendSilent(); },
[=] { sendScheduled(); });
}
addButton(tr::lng_cancel(), [=] { closeBox(); }); addButton(tr::lng_cancel(), [=] { closeBox(); });
initSendWay(); initSendWay();
setupCaption(); setupCaption();
@ -1922,6 +1926,10 @@ void SendFilesBox::setInnerFocus() {
void SendFilesBox::send( void SendFilesBox::send(
Api::SendOptions options, Api::SendOptions options,
bool ctrlShiftEnter) { bool ctrlShiftEnter) {
if (_sendType == Api::SendType::Scheduled && !options.scheduled) {
return sendScheduled();
}
using Way = SendFilesWay; using Way = SendFilesWay;
const auto way = _sendWay ? _sendWay->value() : Way::Files; const auto way = _sendWay ? _sendWay->value() : Way::Files;
@ -1963,14 +1971,9 @@ void SendFilesBox::sendSilent() {
} }
void SendFilesBox::sendScheduled() { void SendFilesBox::sendScheduled() {
const auto callback = crl::guard(this, [=](Api::SendOptions options) { const auto callback = [=](Api::SendOptions options) { send(options); };
send(options);
});
Ui::show( Ui::show(
Box( HistoryView::PrepareScheduleBox(this, callback),
HistoryView::ScheduleBox,
callback,
HistoryView::DefaultScheduleTime()),
LayerOption::KeepOther); LayerOption::KeepOther);
} }

View File

@ -18,6 +18,7 @@ class SessionController;
namespace Api { namespace Api {
struct SendOptions; struct SendOptions;
enum class SendType;
} // namespace Api } // namespace Api
namespace ChatHelpers { namespace ChatHelpers {
@ -57,7 +58,8 @@ public:
Storage::PreparedList &&list, Storage::PreparedList &&list,
const TextWithTags &caption, const TextWithTags &caption,
CompressConfirm compressed, CompressConfirm compressed,
SendLimit limit); SendLimit limit,
Api::SendType sendType);
void setConfirmedCallback( void setConfirmedCallback(
Fn<void( Fn<void(
@ -119,7 +121,8 @@ private:
bool canAddUrls(const QList<QUrl> &urls) const; bool canAddUrls(const QList<QUrl> &urls) const;
bool addFiles(not_null<const QMimeData*> data); bool addFiles(not_null<const QMimeData*> data);
not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
const Api::SendType _sendType = Api::SendType();
QString _titleText; QString _titleText;
int _titleHeight = 0; int _titleHeight = 0;

View File

@ -415,7 +415,7 @@ void ShareBox::createButtons() {
const auto send = addButton(tr::lng_share_confirm(), [=] { const auto send = addButton(tr::lng_share_confirm(), [=] {
submit({}); submit({});
}); });
SetupSendWithoutSound( SetupSendMenu(
send, send,
[=] { return true; }, [=] { return true; },
[=] { submitSilent(); }, [=] { submitSilent(); },
@ -469,14 +469,9 @@ void ShareBox::submitSilent() {
} }
void ShareBox::submitScheduled() { void ShareBox::submitScheduled() {
const auto callback = crl::guard(this, [=](Api::SendOptions options) { const auto callback = [=](Api::SendOptions options) { submit(options); };
submit(options);
});
Ui::show( Ui::show(
Box( HistoryView::PrepareScheduleBox(this, callback),
HistoryView::ScheduleBox,
callback,
HistoryView::DefaultScheduleTime()),
LayerOption::KeepOther); LayerOption::KeepOther);
} }

View File

@ -784,7 +784,7 @@ void MessageLinksParser::apply(
_list = std::move(parsed); _list = std::move(parsed);
} }
void SetupSendWithoutSound( void SetupSendMenu(
not_null<Ui::RpWidget*> button, not_null<Ui::RpWidget*> button,
Fn<bool()> enabled, Fn<bool()> enabled,
Fn<void()> send, Fn<void()> send,

View File

@ -106,7 +106,7 @@ private:
}; };
void SetupSendWithoutSound( void SetupSendMenu(
not_null<Ui::RpWidget*> button, not_null<Ui::RpWidget*> button,
Fn<bool()> enabled, Fn<bool()> enabled,
Fn<void()> send, Fn<void()> send,

View File

@ -237,7 +237,6 @@ void ScheduledMessages::parse(
auto &request = _requests[history]; auto &request = _requests[history];
request.requestId = 0; request.requestId = 0;
auto element = _data.find(history);
list.match([&](const MTPDmessages_messagesNotModified &data) { list.match([&](const MTPDmessages_messagesNotModified &data) {
}, [&](const auto &data) { }, [&](const auto &data) {
_session->data().processUsers(data.vusers()); _session->data().processUsers(data.vusers());
@ -245,38 +244,24 @@ void ScheduledMessages::parse(
const auto &messages = data.vmessages().v; const auto &messages = data.vmessages().v;
if (messages.isEmpty()) { if (messages.isEmpty()) {
if (element != end(_data)) { clearNotSending(history);
_data.erase(element);
element = end(_data);
_updates.fire_copy(history);
}
return; return;
} }
element = _data.emplace(history, List()).first;
auto received = base::flat_set<not_null<HistoryItem*>>(); auto received = base::flat_set<not_null<HistoryItem*>>();
auto &list = element->second; auto clear = base::flat_set<not_null<HistoryItem*>>();
auto &list = _data.emplace(history, List()).first->second;
for (const auto &message : messages) { for (const auto &message : messages) {
if (const auto item = append(history, list, message)) { if (const auto item = append(history, list, message)) {
received.emplace(item); received.emplace(item);
} }
} }
auto clear = base::flat_set<not_null<HistoryItem*>>();
for (const auto &owned : list.items) { for (const auto &owned : list.items) {
const auto item = owned.get(); const auto item = owned.get();
if (!item->isSending() && !received.contains(item)) { if (!item->isSending() && !received.contains(item)) {
clear.emplace(item); clear.emplace(item);
} }
} }
for (const auto item : clear) { updated(history, received, clear);
item->destroy();
}
if (!list.items.empty()) {
sort(list);
} else {
_data.erase(element);
element = end(_data);
}
_updates.fire_copy(history);
}); });
if (!request.requestId) { if (!request.requestId) {
_requests.remove(history); _requests.remove(history);
@ -320,6 +305,38 @@ HistoryItem *ScheduledMessages::append(
return item; return item;
} }
void ScheduledMessages::clearNotSending(not_null<History*> history) {
const auto i = _data.find(history);
if (i == end(_data)) {
return;
}
auto clear = base::flat_set<not_null<HistoryItem*>>();
for (const auto &owned : i->second.items) {
if (!owned->isSending()) {
clear.emplace(owned.get());
}
}
updated(history, {}, clear);
}
void ScheduledMessages::updated(
not_null<History*> history,
const base::flat_set<not_null<HistoryItem*>> &added,
const base::flat_set<not_null<HistoryItem*>> &clear) {
if (!clear.empty()) {
for (const auto item : clear) {
item->destroy();
}
}
const auto i = _data.find(history);
if (i != end(_data)) {
sort(i->second);
}
if (!added.empty() || !clear.empty()) {
_updates.fire_copy(history);
}
}
void ScheduledMessages::sort(List &list) { void ScheduledMessages::sort(List &list) {
ranges::sort(list.items, ranges::less(), &HistoryItem::position); ranges::sort(list.items, ranges::less(), &HistoryItem::position);
} }
@ -330,11 +347,12 @@ void ScheduledMessages::remove(not_null<const HistoryItem*> item) {
Assert(i != end(_data)); Assert(i != end(_data));
auto &list = i->second; auto &list = i->second;
const auto j = list.idByItem.find(item); if (!item->isSending()) {
Assert(j != end(list.idByItem)); const auto j = list.idByItem.find(item);
list.itemById.remove(j->second); Assert(j != end(list.idByItem));
list.idByItem.erase(j); list.itemById.remove(j->second);
list.idByItem.erase(j);
}
const auto k = ranges::find(list.items, item, &OwnedItem::get); const auto k = ranges::find(list.items, item, &OwnedItem::get);
Assert(k != list.items.end()); Assert(k != list.items.end());
k->release(); k->release();

View File

@ -61,6 +61,11 @@ private:
not_null<History*> history, not_null<History*> history,
List &list, List &list,
const MTPMessage &message); const MTPMessage &message);
void clearNotSending(not_null<History*> history);
void updated(
not_null<History*> history,
const base::flat_set<not_null<HistoryItem*>> &added,
const base::flat_set<not_null<HistoryItem*>> &clear);
void sort(List &list); void sort(List &list);
void remove(not_null<const HistoryItem*> item); void remove(not_null<const HistoryItem*> item);
[[nodiscard]] int32 countListHash(const List &list) const; [[nodiscard]] int32 countListHash(const List &list) const;

View File

@ -300,7 +300,7 @@ HistoryWidget::HistoryWidget(
_unreadMentions->addClickHandler([=] { showNextUnreadMention(); }); _unreadMentions->addClickHandler([=] { showNextUnreadMention(); });
_fieldBarCancel->addClickHandler([=] { cancelFieldAreaState(); }); _fieldBarCancel->addClickHandler([=] { cancelFieldAreaState(); });
_send->addClickHandler([=] { sendButtonClicked(); }); _send->addClickHandler([=] { sendButtonClicked(); });
SetupSendWithoutSound(_send, [=] { SetupSendMenu(_send, [=] {
return (_send->type() == Ui::SendButton::Type::Send) return (_send->type() == Ui::SendButton::Type::Send)
&& !_send->isDisabled(); && !_send->isDisabled();
}, [=] { sendSilent(); }, [=] { sendScheduled(); }); }, [=] { sendSilent(); }, [=] { sendScheduled(); });
@ -1747,11 +1747,11 @@ void HistoryWidget::showHistory(
updateControlsGeometry(); updateControlsGeometry();
}, _contactStatus->lifetime()); }, _contactStatus->lifetime());
orderWidgets(); orderWidgets();
controller()->tabbedSelector()->setCurrentPeer(_peer);
} else { } else {
_contactStatus = nullptr; _contactStatus = nullptr;
} }
refreshTabbedPanel(); refreshTabbedPanel();
controller()->tabbedSelector()->setCurrentPeer(_peer);
if (_peer) { if (_peer) {
_unblock->setText(((_peer->isUser() _unblock->setText(((_peer->isUser()
@ -2970,14 +2970,9 @@ void HistoryWidget::sendScheduled() {
if (!_list) { if (!_list) {
return; return;
} }
const auto callback = crl::guard(_list, [=](Api::SendOptions options) { const auto callback = [=](Api::SendOptions options) { send(options); };
send(options);
});
Ui::show( Ui::show(
Box( HistoryView::PrepareScheduleBox(_list, callback),
HistoryView::ScheduleBox,
callback,
HistoryView::DefaultScheduleTime()),
LayerOption::KeepOther); LayerOption::KeepOther);
} }
@ -4192,7 +4187,8 @@ bool HistoryWidget::confirmSendingFiles(
std::move(list), std::move(list),
text, text,
boxCompressConfirm, boxCompressConfirm,
_peer->slowmodeApplied() ? SendLimit::One : SendLimit::Many); _peer->slowmodeApplied() ? SendLimit::One : SendLimit::Many,
Api::SendType::Normal);
_field->setTextWithTags({}); _field->setTextWithTags({});
box->setConfirmedCallback(crl::guard(this, [=]( box->setConfirmedCallback(crl::guard(this, [=](
Storage::PreparedList &&list, Storage::PreparedList &&list,

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/special_buttons.h" #include "ui/special_buttons.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "core/event_filter.h" #include "core/event_filter.h"
#include "history/history.h"
#include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_section.h" #include "chat_helpers/tabbed_section.h"
#include "chat_helpers/tabbed_selector.h" #include "chat_helpers/tabbed_selector.h"
@ -54,6 +55,15 @@ Main::Session &ComposeControls::session() const {
return _window->session(); return _window->session();
} }
void ComposeControls::setHistory(History *history) {
if (_history == history) {
return;
}
_history = history;
_window->tabbedSelector()->setCurrentPeer(
history ? history->peer.get() : nullptr);
}
void ComposeControls::move(int x, int y) { void ComposeControls::move(int x, int y) {
_wrap->move(x, y); _wrap->move(x, y);
} }

View File

@ -58,6 +58,8 @@ public:
[[nodiscard]] Main::Session &session() const; [[nodiscard]] Main::Session &session() const;
void setHistory(History *history);
void move(int x, int y); void move(int x, int y);
void resizeToWidth(int width); void resizeToWidth(int width);
[[nodiscard]] rpl::producer<int> height() const; [[nodiscard]] rpl::producer<int> height() const;
@ -102,6 +104,7 @@ private:
const not_null<QWidget*> _parent; const not_null<QWidget*> _parent;
const not_null<Window::SessionController*> _window; const not_null<Window::SessionController*> _window;
History *_history = nullptr;
Mode _mode = Mode::Normal; Mode _mode = Mode::Normal;
const std::unique_ptr<Ui::RpWidget> _wrap; const std::unique_ptr<Ui::RpWidget> _wrap;

View File

@ -13,7 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/calendar_box.h" #include "boxes/calendar_box.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "chat_helpers/message_field.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_history.h" #include "styles/style_history.h"
@ -88,6 +90,7 @@ public:
bool setFocusFast(); bool setFocusFast();
rpl::producer<QString> value() const; rpl::producer<QString> value() const;
rpl::producer<> submitRequests() const;
QString valueCurrent() const; QString valueCurrent() const;
void showError(); void showError();
@ -117,6 +120,7 @@ private:
object_ptr<Ui::PaddingWrap<Ui::FlatLabel>> _separator1; object_ptr<Ui::PaddingWrap<Ui::FlatLabel>> _separator1;
object_ptr<TimePart> _minute; object_ptr<TimePart> _minute;
rpl::variable<QString> _value; rpl::variable<QString> _value;
rpl::event_stream<> _submitRequests;
style::cursor _cursor = style::cur_default; style::cursor _cursor = style::cur_default;
Ui::Animations::Simple _a_borderShown; Ui::Animations::Simple _a_borderShown;
@ -293,6 +297,29 @@ TimeInput::TimeInput(QWidget *parent, const QString &value)
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
setErrorShown(false); setErrorShown(false);
}, lifetime()); }, lifetime());
const auto submitHour = [=] {
if (hour()) {
_minute->setFocus();
}
};
const auto submitMinute = [=] {
if (minute()) {
if (hour()) {
_submitRequests.fire({});
} else {
_hour->setFocus();
}
}
};
connect(
_hour,
&Ui::MaskedInputField::submitted,
submitHour);
connect(
_minute,
&Ui::MaskedInputField::submitted,
submitMinute);
} }
void TimeInput::putNext(const object_ptr<TimePart> &field, QChar ch) { void TimeInput::putNext(const object_ptr<TimePart> &field, QChar ch) {
@ -350,6 +377,10 @@ rpl::producer<QString> TimeInput::value() const {
return _value.value(); return _value.value();
} }
rpl::producer<> TimeInput::submitRequests() const {
return _submitRequests.events();
}
void TimeInput::paintEvent(QPaintEvent *e) { void TimeInput::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
@ -584,23 +615,30 @@ void ScheduleBox(
const auto shared = std::make_shared<FnMut<void(Api::SendOptions)>>( const auto shared = std::make_shared<FnMut<void(Api::SendOptions)>>(
std::move(done)); std::move(done));
const auto save = [=] { const auto collect = [=] {
auto result = Api::SendOptions();
const auto timeValue = timeInput->valueCurrent().split(':'); const auto timeValue = timeInput->valueCurrent().split(':');
if (timeValue.size() != 2) { if (timeValue.size() != 2) {
timeInput->showError(); timeInput->showError();
return; return 0;
} }
const auto time = QTime(timeValue[0].toInt(), timeValue[1].toInt()); const auto time = QTime(timeValue[0].toInt(), timeValue[1].toInt());
if (!time.isValid()) { if (!time.isValid()) {
timeInput->showError(); timeInput->showError();
return; return 0;
} }
result.scheduled = base::unixtime::serialize( const auto result = base::unixtime::serialize(
QDateTime(date->current(), time)); QDateTime(date->current(), time));
if (result.scheduled <= base::unixtime::now() + kMinimalSchedule) { if (result <= base::unixtime::now() + kMinimalSchedule) {
timeInput->showError(); timeInput->showError();
return 0;
}
return result;
};
const auto save = [=](bool silent) {
auto result = Api::SendOptions();
result.silent = silent;
result.scheduled = collect();
if (!result.scheduled) {
return; return;
} }
@ -608,9 +646,20 @@ void ScheduleBox(
box->closeBox(); box->closeBox();
(*copy)(result); (*copy)(result);
}; };
timeInput->submitRequests(
) | rpl::start_with_next([=] {
save(false);
}, timeInput->lifetime());
box->setFocusCallback([=] { timeInput->setFocusFast(); }); box->setFocusCallback([=] { timeInput->setFocusFast(); });
box->addButton(tr::lng_settings_save(), save); const auto submit = box->addButton(tr::lng_settings_save(), [=] {
save(false);
});
SetupSendMenu(
submit.data(),
[=] { return true; },
[=] { save(true); },
nullptr);
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
} }

View File

@ -21,4 +21,14 @@ void ScheduleBox(
FnMut<void(Api::SendOptions)> done, FnMut<void(Api::SendOptions)> done,
TimeId time); TimeId time);
template <typename Guard, typename Submit>
[[nodiscard]] object_ptr<GenericBox> PrepareScheduleBox(
Guard &&guard,
Submit &&submit) {
return Box(
ScheduleBox,
crl::guard(std::forward<Guard>(guard), std::forward<Submit>(submit)),
DefaultScheduleTime());
}
} // namespace HistoryView } // namespace HistoryView

View File

@ -117,6 +117,8 @@ ScheduledWidget::ScheduledWidget(
ScheduledWidget::~ScheduledWidget() = default; ScheduledWidget::~ScheduledWidget() = default;
void ScheduledWidget::setupComposeControls() { void ScheduledWidget::setupComposeControls() {
_composeControls->setHistory(_history);
_composeControls->height( _composeControls->height(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
updateControlsGeometry(); updateControlsGeometry();
@ -232,7 +234,8 @@ bool ScheduledWidget::confirmSendingFiles(
std::move(list), std::move(list),
text, text,
boxCompressConfirm, boxCompressConfirm,
_history->peer->slowmodeApplied() ? SendLimit::One : SendLimit::Many); _history->peer->slowmodeApplied() ? SendLimit::One : SendLimit::Many,
Api::SendType::Scheduled);
//_field->setTextWithTags({}); //_field->setTextWithTags({});
box->setConfirmedCallback(crl::guard(this, [=]( box->setConfirmedCallback(crl::guard(this, [=](
@ -314,39 +317,28 @@ void ScheduledWidget::uploadFilesAfterConfirmation(
ShowErrorToast(tr::lng_slowmode_no_many(tr::now)); ShowErrorToast(tr::lng_slowmode_no_many(tr::now));
return; return;
} }
auto callback = crl::guard(this, [ auto action = Api::SendAction(_history);
=, action.replyTo = replyTo;
list = std::move(list), action.options = options;
caption = std::move(caption), session().api().sendFiles(
// Strange thing, otherwise std::is_copy_constructible is true. O_o std::move(list),
msvc_bug_workaround = std::make_unique<int>() type,
](Api::SendOptions options) mutable { std::move(caption),
auto action = Api::SendAction(_history); album,
action.replyTo = replyTo; action);
action.options = options;
session().api().sendFiles(
std::move(list),
type,
std::move(caption),
album,
action);
});
Ui::show(
Box(ScheduleBox, std::move(callback), DefaultScheduleTime()),
LayerOption::KeepOther);
} }
void ScheduledWidget::uploadFile( void ScheduledWidget::uploadFile(
const QByteArray &fileContent, const QByteArray &fileContent,
SendMediaType type) { SendMediaType type) {
const auto callback = crl::guard(this, [=](Api::SendOptions options) { const auto callback = [=](Api::SendOptions options) {
auto action = Api::SendAction(_history); auto action = Api::SendAction(_history);
//action.replyTo = replyToId(); //action.replyTo = replyToId();
action.options = options; action.options = options;
session().api().sendFile(fileContent, type, action); session().api().sendFile(fileContent, type, action);
}); };
Ui::show( Ui::show(
Box(ScheduleBox, callback, DefaultScheduleTime()), PrepareScheduleBox(this, callback),
LayerOption::KeepOther); LayerOption::KeepOther);
} }
@ -387,11 +379,9 @@ void ScheduledWidget::send() {
if (_composeControls->getTextWithAppliedMarkdown().text.isEmpty()) { if (_composeControls->getTextWithAppliedMarkdown().text.isEmpty()) {
return; return;
} }
const auto callback = crl::guard(this, [=](Api::SendOptions options) { const auto callback = [=](Api::SendOptions options) { send(options); };
send(options);
});
Ui::show( Ui::show(
Box(ScheduleBox, callback, DefaultScheduleTime()), PrepareScheduleBox(this, callback),
LayerOption::KeepOther); LayerOption::KeepOther);
} }
@ -432,11 +422,11 @@ void ScheduledWidget::send(Api::SendOptions options) {
void ScheduledWidget::sendExistingDocument( void ScheduledWidget::sendExistingDocument(
not_null<DocumentData*> document) { not_null<DocumentData*> document) {
const auto callback = crl::guard(this, [=](Api::SendOptions options) { const auto callback = [=](Api::SendOptions options) {
sendExistingDocument(document, options); sendExistingDocument(document, options);
}); };
Ui::show( Ui::show(
Box(ScheduleBox, callback, DefaultScheduleTime()), PrepareScheduleBox(this, callback),
LayerOption::KeepOther); LayerOption::KeepOther);
} }
@ -470,11 +460,11 @@ bool ScheduledWidget::sendExistingDocument(
} }
void ScheduledWidget::sendExistingPhoto(not_null<PhotoData*> photo) { void ScheduledWidget::sendExistingPhoto(not_null<PhotoData*> photo) {
const auto callback = crl::guard(this, [=](Api::SendOptions options) { const auto callback = [=](Api::SendOptions options) {
sendExistingPhoto(photo, options); sendExistingPhoto(photo, options);
}); };
Ui::show( Ui::show(
Box(ScheduleBox, callback, DefaultScheduleTime()), PrepareScheduleBox(this, callback),
LayerOption::KeepOther); LayerOption::KeepOther);
} }
@ -507,11 +497,11 @@ void ScheduledWidget::sendInlineResult(
Ui::show(Box<InformBox>(errorText)); Ui::show(Box<InformBox>(errorText));
return; return;
} }
const auto callback = crl::guard(this, [=](Api::SendOptions options) { const auto callback = [=](Api::SendOptions options) {
sendInlineResult(result, bot, options); sendInlineResult(result, bot, options);
}); };
Ui::show( Ui::show(
Box(ScheduleBox, callback, DefaultScheduleTime()), PrepareScheduleBox(this, callback),
LayerOption::KeepOther); LayerOption::KeepOther);
} }

View File

@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "api/api_common.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
@ -700,14 +701,17 @@ void PeerMenuShareContactBox(
} }
void PeerMenuCreatePoll(not_null<PeerData*> peer) { void PeerMenuCreatePoll(not_null<PeerData*> peer) {
const auto box = Ui::show(Box<CreatePollBox>(&peer->session())); const auto box = Ui::show(Box<CreatePollBox>(
&peer->session(),
Api::SendType::Normal));
const auto lock = box->lifetime().make_state<bool>(false); const auto lock = box->lifetime().make_state<bool>(false);
box->submitRequests( box->submitRequests(
) | rpl::start_with_next([=](const PollData &result) { ) | rpl::start_with_next([=](const CreatePollBox::Result &result) {
if (std::exchange(*lock, true)) { if (std::exchange(*lock, true)) {
return; return;
} }
auto action = Api::SendAction(peer->owner().history(peer)); auto action = Api::SendAction(peer->owner().history(peer));
action.options = result.options;
if (const auto id = App::main()->currentReplyToIdFor(action.history)) { if (const auto id = App::main()->currentReplyToIdFor(action.history)) {
action.replyTo = id; action.replyTo = id;
} }
@ -715,7 +719,7 @@ void PeerMenuCreatePoll(not_null<PeerData*> peer) {
action.clearDraft = localDraft->textWithTags.text.isEmpty(); action.clearDraft = localDraft->textWithTags.text.isEmpty();
} }
const auto api = &peer->session().api(); const auto api = &peer->session().api();
api->createPoll(result, action, crl::guard(box, [=] { api->createPoll(result.poll, action, crl::guard(box, [=] {
box->closeBox(); box->closeBox();
}), crl::guard(box, [=](const RPCError &error) { }), crl::guard(box, [=](const RPCError &error) {
*lock = false; *lock = false;