mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
[poll-create] Added poll option toggle to set deadline.
This commit is contained in:
@@ -6870,6 +6870,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_polls_create_shuffle_options_about" = "Answers appear in random order for each voter.";
|
||||
"lng_polls_create_set_correct_answer" = "Set Correct Answer";
|
||||
"lng_polls_create_set_correct_answer_about" = "Mark one option as the right answer.";
|
||||
"lng_polls_create_limit_duration" = "Limit Duration";
|
||||
"lng_polls_create_limit_duration_about" = "Automatically close the poll at a set time.";
|
||||
"lng_polls_create_poll_duration" = "Poll Duration";
|
||||
"lng_polls_create_poll_ends" = "Poll ends";
|
||||
"lng_polls_create_hide_results" = "Hide results";
|
||||
"lng_polls_create_hide_results_about" = "If you switch this on, results will appear only after the poll closes.";
|
||||
"lng_polls_create_duration_custom" = "Custom";
|
||||
"lng_polls_create_deadline_title" = "Deadline";
|
||||
"lng_polls_create_deadline_button" = "Set Deadline";
|
||||
"lng_polls_create_deadline_expired" = "The poll deadline has already passed. Please choose a new time.";
|
||||
"lng_polls_create_anonymous" = "Anonymous Voting";
|
||||
"lng_polls_create_multiple_choice" = "Multiple Answers";
|
||||
"lng_polls_create_quiz_mode" = "Quiz Mode";
|
||||
|
||||
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/create_poll_box.h"
|
||||
|
||||
#include "base/call_delayed.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "boxes/premium_limits_box.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/random.h"
|
||||
@@ -47,6 +48,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/dynamic_thumbnails.h"
|
||||
#include "ui/effects/radial_animation.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/ttl_icon.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
@@ -58,6 +60,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/boxes/choose_date_time.h"
|
||||
#include "ui/text/format_values.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
@@ -68,6 +72,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "window/window_session_controller.h"
|
||||
#include "apiwrap.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_chat_helpers.h" // defaultComposeFiles.
|
||||
#include "styles/style_layers.h"
|
||||
@@ -1329,6 +1334,51 @@ void Options::checkLastOption() {
|
||||
addEmptyOption();
|
||||
}
|
||||
|
||||
class DurationIconAction final : public Ui::Menu::Action {
|
||||
public:
|
||||
DurationIconAction(
|
||||
not_null<Ui::Menu::Menu*> parent,
|
||||
const style::Menu &st,
|
||||
not_null<QAction*> action,
|
||||
const QString &tinyText);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
QString _tinyText;
|
||||
|
||||
};
|
||||
|
||||
DurationIconAction::DurationIconAction(
|
||||
not_null<Ui::Menu::Menu*> parent,
|
||||
const style::Menu &st,
|
||||
not_null<QAction*> action,
|
||||
const QString &tinyText)
|
||||
: Ui::Menu::Action(parent, st, action, nullptr, nullptr)
|
||||
, _tinyText(tinyText) {
|
||||
}
|
||||
|
||||
void DurationIconAction::paintEvent(QPaintEvent *e) {
|
||||
Ui::Menu::Action::paintEvent(e);
|
||||
|
||||
const auto &st = this->st();
|
||||
const auto iconPos = st.itemIconPosition;
|
||||
const auto size = st::createPollDurationIconSize;
|
||||
const auto &pos = st::createPollDurationIconPosition;
|
||||
const auto rect = QRect(
|
||||
iconPos.x() + pos.x(),
|
||||
iconPos.y() + pos.y(),
|
||||
size,
|
||||
size);
|
||||
const auto innerRect = rect - st::createPollDurationIconMargins;
|
||||
|
||||
Painter p(this);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
||||
Ui::PaintTimerIcon(p, innerRect, _tinyText, st::menuIconColor->c);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CreatePollBox::CreatePollBox(
|
||||
@@ -1554,6 +1604,8 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
rpl::event_stream<bool> addOptionsForceOff;
|
||||
rpl::event_stream<bool> revotingForceOff;
|
||||
rpl::event_stream<bool> quizForceOff;
|
||||
rpl::variable<int> closePeriod = 0;
|
||||
rpl::variable<TimeId> closeDate = TimeId(0);
|
||||
std::shared_ptr<PollMediaState> descriptionMedia
|
||||
= std::make_shared<PollMediaState>();
|
||||
std::shared_ptr<PollMediaState> solutionMedia
|
||||
@@ -1561,6 +1613,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
std::weak_ptr<PollMediaState> stickerTarget;
|
||||
base::flat_map<FullMsgId, UploadContext> uploads;
|
||||
base::unique_qptr<Ui::PopupMenu> mediaMenu;
|
||||
base::unique_qptr<Ui::PopupMenu> durationMenu;
|
||||
base::unique_qptr<ChatHelpers::TabbedPanel> stickerPanel;
|
||||
std::unique_ptr<TaskQueue> prepareQueue;
|
||||
};
|
||||
@@ -2541,6 +2594,128 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
| rpl::then(state->quizForceOff.events()),
|
||||
st::detailedSettingsButtonStyle);
|
||||
|
||||
const auto duration = AddPollToggleButton(
|
||||
container,
|
||||
tr::lng_polls_create_limit_duration(),
|
||||
tr::lng_polls_create_limit_duration_about(),
|
||||
{
|
||||
.icon = &st::pollBoxFilledPollDeadlineIcon,
|
||||
.background = &st::settingsIconBg1,
|
||||
},
|
||||
rpl::single(false),
|
||||
st::detailedSettingsButtonStyle);
|
||||
|
||||
const auto durationWrap = container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
object_ptr<Ui::VerticalLayout>(container))
|
||||
)->toggleOn(
|
||||
rpl::single(duration->toggled())
|
||||
| rpl::then(duration->toggledChanges()));
|
||||
const auto durationInner = durationWrap->entity();
|
||||
|
||||
auto pollEndsLabelText = state->closePeriod.value(
|
||||
) | rpl::map([=](int) {
|
||||
const auto date = state->closeDate.current();
|
||||
if (date > 0) {
|
||||
return langDateTime(base::unixtime::parse(date));
|
||||
}
|
||||
const auto period = state->closePeriod.current();
|
||||
if (period > 0) {
|
||||
const auto target = base::unixtime::now() + period;
|
||||
return langDateTime(base::unixtime::parse(target));
|
||||
}
|
||||
return QString();
|
||||
});
|
||||
state->closeDate.value(
|
||||
) | rpl::on_next([=](TimeId) {
|
||||
state->closePeriod.force_assign(state->closePeriod.current());
|
||||
}, durationInner->lifetime());
|
||||
|
||||
const auto pollEndsLabel = AddButtonWithLabel(
|
||||
durationInner,
|
||||
tr::lng_polls_create_poll_ends(),
|
||||
std::move(pollEndsLabelText),
|
||||
st::settingsButtonNoIcon);
|
||||
|
||||
const auto show = uiShow();
|
||||
pollEndsLabel->setClickedCallback([=] {
|
||||
state->durationMenu = base::make_unique_q<Ui::PopupMenu>(
|
||||
pollEndsLabel,
|
||||
st::popupMenuWithIcons);
|
||||
const auto &menuSt = state->durationMenu->st().menu;
|
||||
const auto presets = {
|
||||
3600,
|
||||
3 * 3600,
|
||||
8 * 3600,
|
||||
24 * 3600,
|
||||
72 * 3600,
|
||||
};
|
||||
for (const auto seconds : presets) {
|
||||
const auto text = Ui::FormatMuteFor(seconds);
|
||||
auto item = base::make_unique_q<DurationIconAction>(
|
||||
state->durationMenu->menu(),
|
||||
menuSt,
|
||||
Ui::Menu::CreateAction(
|
||||
state->durationMenu->menu().get(),
|
||||
text,
|
||||
[=] {
|
||||
state->closePeriod = seconds;
|
||||
state->closeDate = TimeId(0);
|
||||
}),
|
||||
Ui::FormatTTLTiny(seconds));
|
||||
state->durationMenu->addAction(std::move(item));
|
||||
}
|
||||
state->durationMenu->addAction(
|
||||
tr::lng_polls_create_duration_custom(tr::now),
|
||||
[=] {
|
||||
const auto now = base::unixtime::now();
|
||||
const auto current = (state->closeDate.current() > now)
|
||||
? state->closeDate.current()
|
||||
: (state->closePeriod.current() > 0)
|
||||
? (now + state->closePeriod.current())
|
||||
: (now + 24 * 3600);
|
||||
show->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
Ui::ChooseDateTimeBox(box, {
|
||||
.title = tr::lng_polls_create_deadline_title(),
|
||||
.submit = tr::lng_polls_create_deadline_button(),
|
||||
.done = [=](TimeId time) {
|
||||
state->closeDate = time;
|
||||
state->closePeriod = 0;
|
||||
box->closeBox();
|
||||
},
|
||||
.min = [=] { return base::unixtime::now() + 60; },
|
||||
.time = current,
|
||||
.max = [=] {
|
||||
return base::unixtime::now() + 365 * 24 * 3600;
|
||||
},
|
||||
});
|
||||
}));
|
||||
},
|
||||
&st::menuIconCustomize);
|
||||
state->durationMenu->popup(QCursor::pos());
|
||||
});
|
||||
|
||||
duration->toggledChanges(
|
||||
) | rpl::on_next([=](bool checked) {
|
||||
if (checked && state->closePeriod.current() == 0
|
||||
&& state->closeDate.current() == 0) {
|
||||
state->closePeriod = 24 * 3600;
|
||||
}
|
||||
}, duration->lifetime());
|
||||
|
||||
const auto hideResults = durationInner->add(
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
durationInner,
|
||||
tr::lng_polls_create_hide_results(),
|
||||
st::settingsButtonNoIcon)
|
||||
)->toggleOn(rpl::single(false));
|
||||
|
||||
Ui::AddSkip(durationInner);
|
||||
Ui::AddDividerText(
|
||||
durationInner,
|
||||
tr::lng_polls_create_hide_results_about());
|
||||
|
||||
const auto solution = setupSolution(
|
||||
container,
|
||||
rpl::single(quiz->toggled()) | rpl::then(quiz->toggledChanges()));
|
||||
@@ -2632,15 +2807,31 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
if (quiz->toggled()) {
|
||||
result.solutionMedia = state->solutionMedia->media;
|
||||
}
|
||||
if (duration->toggled()) {
|
||||
const auto closeDate = state->closeDate.current();
|
||||
const auto closePeriod = state->closePeriod.current();
|
||||
if (closeDate > 0) {
|
||||
result.closeDate = closeDate;
|
||||
result.closePeriod = closeDate - base::unixtime::now();
|
||||
} else if (closePeriod > 0) {
|
||||
result.closePeriod = closePeriod;
|
||||
result.closeDate = base::unixtime::now() + closePeriod;
|
||||
}
|
||||
}
|
||||
const auto publicVotes = (showWhoVoted && showWhoVoted->toggled());
|
||||
const auto multiChoice = multiple->toggled();
|
||||
const auto hideResultsEnabled = duration->toggled()
|
||||
&& hideResults->toggled();
|
||||
result.setFlags(Flag(0)
|
||||
| (publicVotes ? Flag::PublicVotes : Flag(0))
|
||||
| (multiChoice ? Flag::MultiChoice : Flag(0))
|
||||
| ((addOptions && addOptions->toggled()) ? Flag::OpenAnswers : Flag(0))
|
||||
| (!revoting->toggled() ? Flag::RevotingDisabled : Flag(0))
|
||||
| (shuffle->toggled() ? Flag::ShuffleAnswers : Flag(0))
|
||||
| (quiz->toggled() ? Flag::Quiz : Flag(0)));
|
||||
| (quiz->toggled() ? Flag::Quiz : Flag(0))
|
||||
| (hideResultsEnabled
|
||||
? Flag::HideResultsUntilClose
|
||||
: Flag(0)));
|
||||
auto text = TextWithEntities{
|
||||
descriptionWithTags.text,
|
||||
TextUtilities::ConvertTextTagsToEntities(
|
||||
@@ -2684,6 +2875,23 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
} else {
|
||||
state->error &= ~Error::Media;
|
||||
}
|
||||
if (duration->toggled()) {
|
||||
const auto now = base::unixtime::now();
|
||||
const auto closeDate = state->closeDate.current();
|
||||
const auto closePeriod = state->closePeriod.current();
|
||||
const auto deadline = (closeDate > 0)
|
||||
? closeDate
|
||||
: (closePeriod > 0)
|
||||
? (now + closePeriod)
|
||||
: 0;
|
||||
if (deadline > 0 && deadline <= now) {
|
||||
state->error |= Error::Deadline;
|
||||
} else {
|
||||
state->error &= ~Error::Deadline;
|
||||
}
|
||||
} else {
|
||||
state->error &= ~Error::Deadline;
|
||||
}
|
||||
};
|
||||
const auto showError = [show = uiShow()](
|
||||
tr::phrase<> text) {
|
||||
@@ -2703,6 +2911,8 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
solution->showError();
|
||||
} else if (state->error & Error::Media) {
|
||||
showError(tr::lng_polls_media_uploading);
|
||||
} else if (state->error & Error::Deadline) {
|
||||
showError(tr::lng_polls_create_deadline_expired);
|
||||
} else if (!state->error) {
|
||||
auto result = collectResult();
|
||||
result.options = sendOptions;
|
||||
|
||||
@@ -66,6 +66,7 @@ private:
|
||||
Other = 0x08,
|
||||
Solution = 0x10,
|
||||
Media = 0x20,
|
||||
Deadline = 0x40,
|
||||
};
|
||||
friend constexpr inline bool is_flag_type(Error) { return true; }
|
||||
using Errors = base::flags<Error>;
|
||||
|
||||
@@ -212,6 +212,10 @@ pollAttach: IconButton(defaultIconButton) {
|
||||
ripple: defaultRippleAnimationBgOver;
|
||||
}
|
||||
|
||||
createPollDurationIconSize: 20px;
|
||||
createPollDurationIconPosition: point(1px, 5px);
|
||||
createPollDurationIconMargins: margins(2px, 2px, 2px, 2px);
|
||||
|
||||
pollDescriptionFieldPadding: margins(22px, 5px, 11px, 5px);
|
||||
pollDescriptionField: InputField(createPollField) {
|
||||
textMargins: margins(0px, 4px, pollAttachTextSkip, 4px);
|
||||
|
||||
Reference in New Issue
Block a user