/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/create_poll_box.h" #include "lang/lang_keys.h" #include "data/data_poll.h" #include "ui/toast/toast.h" #include "ui/wrap/vertical_layout.h" #include "ui/wrap/slide_wrap.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/shadow.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" #include "core/event_filter.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "settings/settings_common.h" #include "base/unique_qptr.h" #include "styles/style_boxes.h" #include "styles/style_settings.h" namespace { constexpr auto kQuestionLimit = 255; constexpr auto kMaxOptionsCount = PollData::kMaxOptions; constexpr auto kOptionLimit = 100; constexpr auto kWarnQuestionLimit = 80; constexpr auto kWarnOptionLimit = 30; constexpr auto kErrorLimit = 99; class Options { public: Options( not_null outer, not_null container); [[nodiscard]] bool isValid() const; [[nodiscard]] rpl::producer isValidChanged() const; [[nodiscard]] std::vector toPollAnswers() const; void focusFirst(); [[nodiscard]] rpl::producer usedCount() const; [[nodiscard]] rpl::producer> scrollToWidget() const; [[nodiscard]] rpl::producer<> backspaceInFront() const; private: class Option { public: static Option Create( not_null outer, not_null container, int position); void toggleRemoveAlways(bool toggled); void show(anim::type animated); void destroy(FnMut done); //[[nodisacrd]] bool hasShadow() const; //void destroyShadow(); [[nodiscard]] bool isEmpty() const; [[nodiscard]] bool isGood() const; [[nodiscard]] bool isTooLong() const; [[nodiscard]] bool hasFocus() const; void setFocus() const; void clearValue(); void setPlaceholder() const; void removePlaceholder() const; not_null field() const; [[nodiscard]] PollAnswer toPollAnswer(int index) const; [[nodiscard]] rpl::producer removeClicks() const; inline bool operator<(const Option &other) const { return field() < other.field(); } friend inline bool operator<( const Option &option, Ui::InputField *field) { return option.field() < field; } friend inline bool operator<( Ui::InputField *field, const Option &option) { return field < option.field(); } private: Option() = default; void createShadow(); void createRemove(); void createWarning(); base::unique_qptr> _field; base::unique_qptr _shadow; base::unique_qptr _remove; rpl::variable *_removeAlways = nullptr; }; [[nodiscard]] bool full() const; //[[nodiscard]] bool correctShadows() const; //void fixShadows(); void removeEmptyTail(); void addEmptyOption(); void checkLastOption(); void validateState(); void fixAfterErase(); void destroy(Option &&option); void removeDestroyed(not_null field); int findField(not_null field) const; not_null _outer; not_null _container; int _position = 0; std::vector