mirror of https://github.com/procxx/kepka.git
Always show Create button, show error messages.
Fixes #7058, fixes #7059.
This commit is contained in:
parent
6a581830f4
commit
bb64285c3a
|
@ -2204,6 +2204,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_polls_create_multiple_choice" = "Multiple Answers";
|
"lng_polls_create_multiple_choice" = "Multiple Answers";
|
||||||
"lng_polls_create_quiz_mode" = "Quiz Mode";
|
"lng_polls_create_quiz_mode" = "Quiz Mode";
|
||||||
"lng_polls_create_button" = "Create";
|
"lng_polls_create_button" = "Create";
|
||||||
|
"lng_polls_choose_question" = "Please enter a question.";
|
||||||
|
"lng_polls_choose_answers" = "Please enter at least two options.";
|
||||||
|
"lng_polls_choose_correct" = "Please choose the correct answer.";
|
||||||
|
|
||||||
"lng_polls_poll_results_title" = "Poll results";
|
"lng_polls_poll_results_title" = "Poll results";
|
||||||
"lng_polls_quiz_results_title" = "Quiz results";
|
"lng_polls_quiz_results_title" = "Quiz results";
|
||||||
|
|
|
@ -48,8 +48,9 @@ public:
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
bool chooseCorrectEnabled);
|
bool chooseCorrectEnabled);
|
||||||
|
|
||||||
|
[[nodiscard]] bool hasOptions() const;
|
||||||
[[nodiscard]] bool isValid() const;
|
[[nodiscard]] bool isValid() const;
|
||||||
[[nodiscard]] rpl::producer<bool> isValidChanged() const;
|
[[nodiscard]] bool hasCorrect() const;
|
||||||
[[nodiscard]] std::vector<PollAnswer> toPollAnswers() const;
|
[[nodiscard]] std::vector<PollAnswer> toPollAnswers() const;
|
||||||
void focusFirst();
|
void focusFirst();
|
||||||
|
|
||||||
|
@ -139,8 +140,10 @@ private:
|
||||||
int _position = 0;
|
int _position = 0;
|
||||||
std::vector<std::unique_ptr<Option>> _list;
|
std::vector<std::unique_ptr<Option>> _list;
|
||||||
std::vector<std::unique_ptr<Option>> _destroyed;
|
std::vector<std::unique_ptr<Option>> _destroyed;
|
||||||
rpl::variable<bool> _valid = false;
|
|
||||||
rpl::variable<int> _usedCount = 0;
|
rpl::variable<int> _usedCount = 0;
|
||||||
|
bool _hasOptions = false;
|
||||||
|
bool _isValid = false;
|
||||||
|
bool _hasCorrect = false;
|
||||||
rpl::event_stream<not_null<QWidget*>> _scrollToWidget;
|
rpl::event_stream<not_null<QWidget*>> _scrollToWidget;
|
||||||
rpl::event_stream<> _backspaceInFront;
|
rpl::event_stream<> _backspaceInFront;
|
||||||
|
|
||||||
|
@ -470,12 +473,16 @@ bool Options::full() const {
|
||||||
return (_list.size() == kMaxOptionsCount);
|
return (_list.size() == kMaxOptionsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Options::isValid() const {
|
bool Options::hasOptions() const {
|
||||||
return _valid.current();
|
return _hasOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<bool> Options::isValidChanged() const {
|
bool Options::isValid() const {
|
||||||
return _valid.changes();
|
return _isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Options::hasCorrect() const {
|
||||||
|
return _hasCorrect;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<int> Options::usedCount() const {
|
rpl::producer<int> Options::usedCount() const {
|
||||||
|
@ -696,10 +703,11 @@ void Options::removeDestroyed(not_null<Option*> option) {
|
||||||
|
|
||||||
void Options::validateState() {
|
void Options::validateState() {
|
||||||
checkLastOption();
|
checkLastOption();
|
||||||
_valid = (ranges::count_if(_list, &Option::isGood) > 1)
|
_hasOptions = (ranges::count_if(_list, &Option::isGood) > 1);
|
||||||
&& (ranges::find_if(_list, &Option::isTooLong) == end(_list))
|
_isValid = _hasOptions
|
||||||
&& (!_chooseCorrectGroup
|
&& (ranges::find_if(_list, &Option::isTooLong) == end(_list));
|
||||||
|| ranges::find_if(_list, &Option::isCorrect) != end(_list));
|
_hasCorrect = ranges::find_if(_list, &Option::isCorrect) != end(_list);
|
||||||
|
|
||||||
const auto lastEmpty = !_list.empty() && _list.back()->isEmpty();
|
const auto lastEmpty = !_list.empty() && _list.back()->isEmpty();
|
||||||
_usedCount = _list.size() - (lastEmpty ? 1 : 0);
|
_usedCount = _list.size() - (lastEmpty ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
@ -789,7 +797,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||||
using namespace Settings;
|
using namespace Settings;
|
||||||
|
|
||||||
const auto id = rand_value<uint64>();
|
const auto id = rand_value<uint64>();
|
||||||
const auto valid = lifetime().make_state<rpl::event_stream<bool>>();
|
const auto error = lifetime().make_state<Errors>(Error::Question);
|
||||||
|
|
||||||
auto result = object_ptr<Ui::VerticalLayout>(this);
|
auto result = object_ptr<Ui::VerticalLayout>(this);
|
||||||
const auto container = result.data();
|
const auto container = result.data();
|
||||||
|
@ -910,8 +918,41 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||||
| (quiz->checked() ? Flag::Quiz : Flag(0)));
|
| (quiz->checked() ? Flag::Quiz : Flag(0)));
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
const auto send = [=](Api::SendOptions options) {
|
const auto collectError = [=] {
|
||||||
_submitRequests.fire({ collectResult(), options });
|
if (isValidQuestion()) {
|
||||||
|
*error &= ~Error::Question;
|
||||||
|
} else {
|
||||||
|
*error |= Error::Question;
|
||||||
|
}
|
||||||
|
if (!options->hasOptions()) {
|
||||||
|
*error |= Error::Options;
|
||||||
|
} else if (!options->isValid()) {
|
||||||
|
*error |= Error::Other;
|
||||||
|
} else {
|
||||||
|
*error &= ~(Error::Options | Error::Other);
|
||||||
|
}
|
||||||
|
if (quiz->checked() && !options->hasCorrect()) {
|
||||||
|
*error |= Error::Correct;
|
||||||
|
} else {
|
||||||
|
*error &= ~Error::Correct;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto showError = [=](const QString &text) {
|
||||||
|
Ui::Toast::Show(text);
|
||||||
|
};
|
||||||
|
const auto send = [=](Api::SendOptions sendOptions) {
|
||||||
|
collectError();
|
||||||
|
if (*error & Error::Question) {
|
||||||
|
showError(tr::lng_polls_choose_question(tr::now));
|
||||||
|
question->setFocus();
|
||||||
|
} else if (*error & Error::Options) {
|
||||||
|
showError(tr::lng_polls_choose_answers(tr::now));
|
||||||
|
options->focusFirst();
|
||||||
|
} else if (*error & Error::Correct) {
|
||||||
|
showError(tr::lng_polls_choose_correct(tr::now));
|
||||||
|
} else if (!*error) {
|
||||||
|
_submitRequests.fire({ collectResult(), sendOptions });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const auto sendSilent = [=] {
|
const auto sendSilent = [=] {
|
||||||
auto options = Api::SendOptions();
|
auto options = Api::SendOptions();
|
||||||
|
@ -926,36 +967,6 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||||
send),
|
send),
|
||||||
Ui::LayerOption::KeepOther);
|
Ui::LayerOption::KeepOther);
|
||||||
};
|
};
|
||||||
const auto updateValid = [=] {
|
|
||||||
valid->fire(isValidQuestion() && options->isValid());
|
|
||||||
};
|
|
||||||
connect(question, &Ui::InputField::changed, [=] {
|
|
||||||
updateValid();
|
|
||||||
});
|
|
||||||
valid->events_starting_with(
|
|
||||||
false
|
|
||||||
) | rpl::distinct_until_changed(
|
|
||||||
) | rpl::start_with_next([=](bool valid) {
|
|
||||||
clearButtons();
|
|
||||||
if (valid) {
|
|
||||||
const auto submit = addButton(
|
|
||||||
tr::lng_polls_create_button(),
|
|
||||||
[=] { send({}); });
|
|
||||||
if (_sendType == Api::SendType::Normal) {
|
|
||||||
SetupSendMenuAndShortcuts(
|
|
||||||
submit.data(),
|
|
||||||
[=] { return SendMenuType::Scheduled; },
|
|
||||||
sendSilent,
|
|
||||||
sendScheduled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
|
||||||
}, lifetime());
|
|
||||||
|
|
||||||
options->isValidChanged(
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
updateValid();
|
|
||||||
}, lifetime());
|
|
||||||
|
|
||||||
options->scrollToWidget(
|
options->scrollToWidget(
|
||||||
) | rpl::start_with_next([=](not_null<QWidget*> widget) {
|
) | rpl::start_with_next([=](not_null<QWidget*> widget) {
|
||||||
|
@ -967,6 +978,22 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||||
FocusAtEnd(question);
|
FocusAtEnd(question);
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
const auto submit = addButton(
|
||||||
|
tr::lng_polls_create_button(),
|
||||||
|
[=] { send({}); });
|
||||||
|
if (_sendType == Api::SendType::Normal) {
|
||||||
|
const auto sendMenuType = [=] {
|
||||||
|
collectError();
|
||||||
|
return *error ? SendMenuType::Disabled : SendMenuType::Scheduled;
|
||||||
|
};
|
||||||
|
SetupSendMenuAndShortcuts(
|
||||||
|
submit.data(),
|
||||||
|
sendMenuType,
|
||||||
|
sendSilent,
|
||||||
|
sendScheduled);
|
||||||
|
}
|
||||||
|
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/abstract_box.h"
|
#include "boxes/abstract_box.h"
|
||||||
#include "api/api_common.h"
|
#include "api/api_common.h"
|
||||||
#include "data/data_poll.h"
|
#include "data/data_poll.h"
|
||||||
|
#include "base/flags.h"
|
||||||
|
|
||||||
struct PollData;
|
struct PollData;
|
||||||
|
|
||||||
|
@ -44,6 +45,15 @@ protected:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class Error {
|
||||||
|
Question = 0x01,
|
||||||
|
Options = 0x02,
|
||||||
|
Correct = 0x04,
|
||||||
|
Other = 0x08,
|
||||||
|
};
|
||||||
|
friend constexpr inline bool is_flag_type(Error) { return true; }
|
||||||
|
using Errors = base::flags<Error>;
|
||||||
|
|
||||||
object_ptr<Ui::RpWidget> setupContent();
|
object_ptr<Ui::RpWidget> setupContent();
|
||||||
not_null<Ui::InputField*> setupQuestion(
|
not_null<Ui::InputField*> setupQuestion(
|
||||||
not_null<Ui::VerticalLayout*> container);
|
not_null<Ui::VerticalLayout*> container);
|
||||||
|
|
Loading…
Reference in New Issue