mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-21 10:53:21 +00:00
Support creating polls from bot keyboards.
This commit is contained in:
parent
c3aa2abe11
commit
d0597407d8
@ -547,6 +547,7 @@ keyboardButtonGame#50f41ccf text:string = KeyboardButton;
|
||||
keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
|
||||
keyboardButtonUrlAuth#10b78d29 flags:# text:string fwd_text:flags.0?string url:string button_id:int = KeyboardButton;
|
||||
inputKeyboardButtonUrlAuth#d02e7fd4 flags:# request_write_access:flags.0?true text:string fwd_text:flags.1?string url:string bot:InputUser = KeyboardButton;
|
||||
keyboardButtonRequestPoll#bbc7515d flags:# quiz:flags.0?Bool text:string = KeyboardButton;
|
||||
|
||||
keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
|
||||
|
||||
|
@ -45,7 +45,8 @@ public:
|
||||
Options(
|
||||
not_null<QWidget*> outer,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<Main::Session*> session);
|
||||
not_null<Main::Session*> session,
|
||||
bool chooseCorrectEnabled);
|
||||
|
||||
[[nodiscard]] bool isValid() const;
|
||||
[[nodiscard]] rpl::producer<bool> isValidChanged() const;
|
||||
@ -128,6 +129,8 @@ private:
|
||||
void destroy(std::unique_ptr<Option> option);
|
||||
void removeDestroyed(not_null<Option*> field);
|
||||
int findField(not_null<Ui::InputField*> field) const;
|
||||
[[nodiscard]] auto createChooseCorrectGroup()
|
||||
-> std::shared_ptr<Ui::RadiobuttonGroup>;
|
||||
|
||||
not_null<QWidget*> _outer;
|
||||
not_null<Ui::VerticalLayout*> _container;
|
||||
@ -236,9 +239,11 @@ Options::Option::Option(
|
||||
createRemove();
|
||||
createWarning();
|
||||
enableChooseCorrect(group);
|
||||
_correctShown.stop();
|
||||
if (_correct) {
|
||||
_correct->finishAnimating();
|
||||
}
|
||||
updateFieldGeometry();
|
||||
}
|
||||
|
||||
bool Options::Option::hasShadow() const {
|
||||
@ -449,10 +454,14 @@ rpl::producer<Qt::MouseButton> Options::Option::removeClicks() const {
|
||||
Options::Options(
|
||||
not_null<QWidget*> outer,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<Main::Session*> session)
|
||||
not_null<Main::Session*> session,
|
||||
bool chooseCorrectEnabled)
|
||||
: _outer(outer)
|
||||
, _container(container)
|
||||
, _session(session)
|
||||
, _chooseCorrectGroup(chooseCorrectEnabled
|
||||
? createChooseCorrectGroup()
|
||||
: nullptr)
|
||||
, _position(_container->count()) {
|
||||
checkLastOption();
|
||||
}
|
||||
@ -518,15 +527,18 @@ void Options::focusFirst() {
|
||||
_list.front()->setFocus();
|
||||
}
|
||||
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> Options::createChooseCorrectGroup() {
|
||||
auto result = std::make_shared<Ui::RadiobuttonGroup>(0);
|
||||
result->setChangedCallback([=](int) {
|
||||
validateState();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void Options::enableChooseCorrect(bool enabled) {
|
||||
_chooseCorrectGroup = enabled
|
||||
? std::make_shared<Ui::RadiobuttonGroup>(0)
|
||||
? createChooseCorrectGroup()
|
||||
: nullptr;
|
||||
if (_chooseCorrectGroup) {
|
||||
_chooseCorrectGroup->setChangedCallback([=](int) {
|
||||
validateState();
|
||||
});
|
||||
}
|
||||
validateState();
|
||||
for (auto &option : _list) {
|
||||
option->enableChooseCorrect(_chooseCorrectGroup);
|
||||
@ -712,10 +724,12 @@ void Options::checkLastOption() {
|
||||
CreatePollBox::CreatePollBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
PublicVotes publicVotes,
|
||||
PollData::Flags chosen,
|
||||
PollData::Flags disabled,
|
||||
Api::SendType sendType)
|
||||
: _session(session)
|
||||
, _publicVotes(publicVotes)
|
||||
, _chosen(chosen)
|
||||
, _disabled(disabled)
|
||||
, _sendType(sendType) {
|
||||
}
|
||||
|
||||
@ -792,7 +806,8 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
const auto options = lifetime().make_state<Options>(
|
||||
getDelegate()->outerContainer(),
|
||||
container,
|
||||
_session);
|
||||
_session,
|
||||
(_chosen & PollData::Flag::Quiz));
|
||||
auto limit = options->usedCount() | rpl::after_next([=](int count) {
|
||||
setCloseByEscape(!count);
|
||||
setCloseByOutsideClick(!count);
|
||||
@ -815,12 +830,12 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
AddSkip(container);
|
||||
AddSubsectionTitle(container, tr::lng_polls_create_settings());
|
||||
|
||||
const auto anonymous = (_publicVotes == PublicVotes::Enabled)
|
||||
const auto anonymous = (!(_disabled & PollData::Flag::PublicVotes))
|
||||
? container->add(
|
||||
object_ptr<Ui::Checkbox>(
|
||||
container,
|
||||
tr::lng_polls_create_anonymous(tr::now),
|
||||
true,
|
||||
!(_chosen & PollData::Flag::PublicVotes),
|
||||
st::defaultCheckbox),
|
||||
st::createPollCheckboxMargin)
|
||||
: nullptr;
|
||||
@ -828,16 +843,19 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
object_ptr<Ui::Checkbox>(
|
||||
container,
|
||||
tr::lng_polls_create_multiple_choice(tr::now),
|
||||
false,
|
||||
(_chosen & PollData::Flag::MultiChoice),
|
||||
st::defaultCheckbox),
|
||||
st::createPollCheckboxMargin);
|
||||
const auto quiz = container->add(
|
||||
object_ptr<Ui::Checkbox>(
|
||||
container,
|
||||
tr::lng_polls_create_quiz_mode(tr::now),
|
||||
false,
|
||||
(_chosen & PollData::Flag::Quiz),
|
||||
st::defaultCheckbox),
|
||||
st::createPollCheckboxMargin);
|
||||
quiz->setDisabled(_disabled & PollData::Flag::Quiz);
|
||||
multiple->setDisabled((_disabled & PollData::Flag::MultiChoice)
|
||||
|| (_chosen & PollData::Flag::Quiz));
|
||||
|
||||
using namespace rpl::mappers;
|
||||
quiz->checkedChanges(
|
||||
@ -845,14 +863,14 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
if (checked && multiple->checked()) {
|
||||
multiple->setChecked(false);
|
||||
}
|
||||
multiple->setDisabled(checked);
|
||||
multiple->setDisabled(checked
|
||||
|| (_disabled & PollData::Flag::MultiChoice));
|
||||
options->enableChooseCorrect(checked);
|
||||
}, quiz->lifetime());
|
||||
|
||||
multiple->events(
|
||||
) | rpl::filter([=](not_null<QEvent*> e) {
|
||||
return (e->type() == QEvent::MouseButtonPress)
|
||||
&& multiple->isDisabled();
|
||||
return (e->type() == QEvent::MouseButtonPress) && quiz->checked();
|
||||
}) | rpl::start_with_next([=] {
|
||||
Ui::Toast::Show("Quiz has only one right answer.");
|
||||
}, multiple->lifetime());
|
||||
|
@ -27,15 +27,12 @@ public:
|
||||
PollData poll;
|
||||
Api::SendOptions options;
|
||||
};
|
||||
enum class PublicVotes {
|
||||
Enabled,
|
||||
Disabled,
|
||||
};
|
||||
|
||||
CreatePollBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
PublicVotes publicVotes,
|
||||
PollData::Flags chosen,
|
||||
PollData::Flags disabled,
|
||||
Api::SendType sendType);
|
||||
|
||||
rpl::producer<Result> submitRequests() const;
|
||||
@ -52,7 +49,8 @@ private:
|
||||
not_null<Ui::VerticalLayout*> container);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
const PublicVotes _publicVotes = PublicVotes();
|
||||
const PollData::Flags _chosen = PollData::Flags();
|
||||
const PollData::Flags _disabled = PollData::Flags();
|
||||
const Api::SendType _sendType = Api::SendType();
|
||||
Fn<void()> _setInnerFocus;
|
||||
Fn<rpl::producer<bool>()> _dataIsValidValue;
|
||||
|
@ -751,6 +751,17 @@ int PeerData::slowmodeSecondsLeft() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PeerData::canSendPolls() const {
|
||||
if (const auto user = asUser()) {
|
||||
return user->isBot();
|
||||
} else if (const auto chat = asChat()) {
|
||||
return chat->canSendPolls();
|
||||
} else if (const auto channel = asChannel()) {
|
||||
return channel->canSendPolls();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace Data {
|
||||
|
||||
std::vector<ChatRestrictions> ListOfRestrictions() {
|
||||
|
@ -191,6 +191,7 @@ public:
|
||||
[[nodiscard]] bool canRevokeFullHistory() const;
|
||||
[[nodiscard]] bool slowmodeApplied() const;
|
||||
[[nodiscard]] int slowmodeSecondsLeft() const;
|
||||
[[nodiscard]] bool canSendPolls() const;
|
||||
|
||||
[[nodiscard]] UserData *asUser();
|
||||
[[nodiscard]] const UserData *asUser() const;
|
||||
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "core/application.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "window/window_peer_menu.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "data/data_peer.h"
|
||||
@ -115,6 +116,19 @@ void activateBotCommand(
|
||||
}));
|
||||
} break;
|
||||
|
||||
case ButtonType::RequestPoll: {
|
||||
hideSingleUseKeyboard(msg);
|
||||
auto chosen = PollData::Flags();
|
||||
auto disabled = PollData::Flags();
|
||||
if (!button->data.isEmpty()) {
|
||||
disabled |= PollData::Flag::Quiz;
|
||||
if (button->data[0]) {
|
||||
chosen |= PollData::Flag::Quiz;
|
||||
}
|
||||
}
|
||||
Window::PeerMenuCreatePoll(msg->history()->peer, chosen, disabled);
|
||||
} break;
|
||||
|
||||
case ButtonType::SwitchInlineSame:
|
||||
case ButtonType::SwitchInline: {
|
||||
if (auto m = App::main()) {
|
||||
|
@ -843,6 +843,21 @@ void HistoryMessageReplyMarkup::createFromButtonRows(
|
||||
}, [&](const MTPDinputKeyboardButtonUrlAuth &data) {
|
||||
LOG(("API Error: inputKeyboardButtonUrlAuth received."));
|
||||
// Should not get those for the users.
|
||||
}, [&](const MTPDkeyboardButtonRequestPoll &data) {
|
||||
const auto quiz = [&] {
|
||||
if (!data.vquiz()) {
|
||||
return QByteArray();
|
||||
}
|
||||
return data.vquiz()->match([&](const MTPDboolTrue&) {
|
||||
return QByteArray(1, 1);
|
||||
}, [&](const MTPDboolFalse&) {
|
||||
return QByteArray(1, 0);
|
||||
});
|
||||
}();
|
||||
row.emplace_back(
|
||||
Type::RequestPoll,
|
||||
qs(data.vtext()),
|
||||
quiz);
|
||||
});
|
||||
}
|
||||
if (!row.empty()) {
|
||||
|
@ -164,6 +164,7 @@ struct HistoryMessageMarkupButton {
|
||||
Callback,
|
||||
RequestPhone,
|
||||
RequestLocation,
|
||||
RequestPoll,
|
||||
SwitchInline,
|
||||
SwitchInlineSame,
|
||||
Game,
|
||||
|
@ -413,6 +413,11 @@ void Filler::addUserActions(not_null<UserData*> user) {
|
||||
tr::lng_profile_invite_to_group(tr::now),
|
||||
[=] { AddBotToGroup::Start(controller, user); });
|
||||
}
|
||||
if (user->canSendPolls()) {
|
||||
_addAction(
|
||||
tr::lng_polls_create(tr::now),
|
||||
[=] { PeerMenuCreatePoll(user); });
|
||||
}
|
||||
if (user->canExportChatHistory()) {
|
||||
_addAction(
|
||||
tr::lng_profile_export_chat(tr::now),
|
||||
@ -707,12 +712,18 @@ void PeerMenuShareContactBox(
|
||||
}));
|
||||
}
|
||||
|
||||
void PeerMenuCreatePoll(not_null<PeerData*> peer) {
|
||||
void PeerMenuCreatePoll(
|
||||
not_null<PeerData*> peer,
|
||||
PollData::Flags chosen,
|
||||
PollData::Flags disabled) {
|
||||
if (peer->isChannel() && !peer->isMegagroup()) {
|
||||
chosen &= ~PollData::Flag::PublicVotes;
|
||||
disabled |= PollData::Flag::PublicVotes;
|
||||
}
|
||||
const auto box = Ui::show(Box<CreatePollBox>(
|
||||
&peer->session(),
|
||||
((peer->isChannel() && !peer->isMegagroup())
|
||||
? CreatePollBox::PublicVotes::Disabled
|
||||
: CreatePollBox::PublicVotes::Enabled),
|
||||
chosen,
|
||||
disabled,
|
||||
Api::SendType::Normal));
|
||||
const auto lock = box->lifetime().make_state<bool>(false);
|
||||
box->submitRequests(
|
||||
|
@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "data/data_poll.h"
|
||||
|
||||
class History;
|
||||
|
||||
namespace Ui {
|
||||
@ -58,7 +60,10 @@ void PeerMenuAddChannelMembers(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<ChannelData*> channel);
|
||||
//void PeerMenuUngroupFeed(not_null<Data::Feed*> feed); // #feed
|
||||
void PeerMenuCreatePoll(not_null<PeerData*> peer);
|
||||
void PeerMenuCreatePoll(
|
||||
not_null<PeerData*> peer,
|
||||
PollData::Flags chosen = PollData::Flags(),
|
||||
PollData::Flags disabled = PollData::Flags());
|
||||
void PeerMenuBlockUserBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<Window::Controller*> window,
|
||||
|
Loading…
Reference in New Issue
Block a user