Improve recipients selection in business features.
This commit is contained in:
parent
e3f6c189a7
commit
00dcf11691
|
@ -2285,6 +2285,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_chatbots_remove" = "Remove Bot";
|
"lng_chatbots_remove" = "Remove Bot";
|
||||||
"lng_chatbots_not_found" = "Chatbot not found.";
|
"lng_chatbots_not_found" = "Chatbot not found.";
|
||||||
"lng_chatbots_add" = "Add";
|
"lng_chatbots_add" = "Add";
|
||||||
|
"lng_chatbots_info_url" = "https://telegram.org/privacy";
|
||||||
|
|
||||||
"lng_boost_channel_button" = "Boost Channel";
|
"lng_boost_channel_button" = "Boost Channel";
|
||||||
"lng_boost_group_button" = "Boost Group";
|
"lng_boost_group_button" = "Boost Group";
|
||||||
|
|
|
@ -669,17 +669,6 @@ bool ShowSearchTagsPromo(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShowAboutBusinessChatbots(
|
|
||||||
Window::SessionController *controller,
|
|
||||||
const Match &match,
|
|
||||||
const QVariant &context) {
|
|
||||||
if (!controller) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
controller->showToast(u"Cool feature, yeah.."_q); AssertIsDebug();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExportTestChatTheme(
|
void ExportTestChatTheme(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<const Data::CloudTheme*> theme) {
|
not_null<const Data::CloudTheme*> theme) {
|
||||||
|
@ -1048,10 +1037,6 @@ const std::vector<LocalUrlHandler> &InternalUrlHandlers() {
|
||||||
u"about_tags"_q,
|
u"about_tags"_q,
|
||||||
ShowSearchTagsPromo
|
ShowSearchTagsPromo
|
||||||
},
|
},
|
||||||
{
|
|
||||||
u"about_business_chatbots"_q,
|
|
||||||
ShowAboutBusinessChatbots
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ struct BusinessChats {
|
||||||
BusinessChatTypes types;
|
BusinessChatTypes types;
|
||||||
std::vector<not_null<UserData*>> list;
|
std::vector<not_null<UserData*>> list;
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const {
|
||||||
|
return !types && list.empty();
|
||||||
|
}
|
||||||
|
|
||||||
friend inline bool operator==(
|
friend inline bool operator==(
|
||||||
const BusinessChats &a,
|
const BusinessChats &a,
|
||||||
const BusinessChats &b) = default;
|
const BusinessChats &b) = default;
|
||||||
|
@ -193,7 +197,7 @@ enum class AwayScheduleType : uchar {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AwaySchedule {
|
struct AwaySchedule {
|
||||||
AwayScheduleType type = AwayScheduleType::Always;
|
AwayScheduleType type = AwayScheduleType::Never;
|
||||||
WorkingInterval customInterval;
|
WorkingInterval customInterval;
|
||||||
|
|
||||||
friend inline bool operator==(
|
friend inline bool operator==(
|
||||||
|
|
|
@ -109,20 +109,20 @@ void BusinessInfo::saveAwaySettings(
|
||||||
const auto &was = _awaySettings;
|
const auto &was = _awaySettings;
|
||||||
if (was == data) {
|
if (was == data) {
|
||||||
return;
|
return;
|
||||||
|
} else if (!data || data.shortcutId) {
|
||||||
|
using Flag = MTPaccount_UpdateBusinessAwayMessage::Flag;
|
||||||
|
const auto session = &_owner->session();
|
||||||
|
session->api().request(MTPaccount_UpdateBusinessAwayMessage(
|
||||||
|
MTP_flags(data ? Flag::f_message : Flag()),
|
||||||
|
data ? ToMTP(data) : MTPInputBusinessAwayMessage()
|
||||||
|
)).fail([=](const MTP::Error &error) {
|
||||||
|
_awaySettings = was;
|
||||||
|
_awaySettingsChanged.fire({});
|
||||||
|
if (fail) {
|
||||||
|
fail(error.type());
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
}
|
}
|
||||||
using Flag = MTPaccount_UpdateBusinessAwayMessage::Flag;
|
|
||||||
const auto session = &_owner->session();
|
|
||||||
session->api().request(MTPaccount_UpdateBusinessAwayMessage(
|
|
||||||
MTP_flags(data ? Flag::f_message : Flag()),
|
|
||||||
data ? ToMTP(data) : MTPInputBusinessAwayMessage()
|
|
||||||
)).fail([=](const MTP::Error &error) {
|
|
||||||
_awaySettings = was;
|
|
||||||
_awaySettingsChanged.fire({});
|
|
||||||
if (fail) {
|
|
||||||
fail(error.type());
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
|
|
||||||
_awaySettings = std::move(data);
|
_awaySettings = std::move(data);
|
||||||
_awaySettingsChanged.fire({});
|
_awaySettingsChanged.fire({});
|
||||||
}
|
}
|
||||||
|
@ -153,20 +153,20 @@ void BusinessInfo::saveGreetingSettings(
|
||||||
const auto &was = _greetingSettings;
|
const auto &was = _greetingSettings;
|
||||||
if (was == data) {
|
if (was == data) {
|
||||||
return;
|
return;
|
||||||
|
} else if (!data || data.shortcutId) {
|
||||||
|
using Flag = MTPaccount_UpdateBusinessGreetingMessage::Flag;
|
||||||
|
_owner->session().api().request(
|
||||||
|
MTPaccount_UpdateBusinessGreetingMessage(
|
||||||
|
MTP_flags(data ? Flag::f_message : Flag()),
|
||||||
|
data ? ToMTP(data) : MTPInputBusinessGreetingMessage())
|
||||||
|
).fail([=](const MTP::Error &error) {
|
||||||
|
_greetingSettings = was;
|
||||||
|
_greetingSettingsChanged.fire({});
|
||||||
|
if (fail) {
|
||||||
|
fail(error.type());
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
}
|
}
|
||||||
using Flag = MTPaccount_UpdateBusinessGreetingMessage::Flag;
|
|
||||||
_owner->session().api().request(
|
|
||||||
MTPaccount_UpdateBusinessGreetingMessage(
|
|
||||||
MTP_flags(data ? Flag::f_message : Flag()),
|
|
||||||
data ? ToMTP(data) : MTPInputBusinessGreetingMessage())
|
|
||||||
).fail([=](const MTP::Error &error) {
|
|
||||||
_greetingSettings = was;
|
|
||||||
_greetingSettingsChanged.fire({});
|
|
||||||
if (fail) {
|
|
||||||
fail(error.type());
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
|
|
||||||
_greetingSettings = std::move(data);
|
_greetingSettings = std::move(data);
|
||||||
_greetingSettingsChanged.fire({});
|
_greetingSettingsChanged.fire({});
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,12 @@ public:
|
||||||
}
|
}
|
||||||
virtual void fillTopBarMenu(const Ui::Menu::MenuCallback &addAction);
|
virtual void fillTopBarMenu(const Ui::Menu::MenuCallback &addAction);
|
||||||
|
|
||||||
|
[[nodiscard]] virtual bool closeByOutsideClick() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual void checkBeforeClose(Fn<void()> close) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
[[nodiscard]] virtual rpl::producer<QString> title() = 0;
|
[[nodiscard]] virtual rpl::producer<QString> title() = 0;
|
||||||
[[nodiscard]] virtual rpl::producer<QString> subtitle() {
|
[[nodiscard]] virtual rpl::producer<QString> subtitle() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -410,8 +410,10 @@ void WrapWidget::setupTopBarMenuToggle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WrapWidget::checkBeforeClose(Fn<void()> close) {
|
void WrapWidget::checkBeforeClose(Fn<void()> close) {
|
||||||
_controller->parentController()->hideLayer();
|
_content->checkBeforeClose(crl::guard(this, [=] {
|
||||||
close();
|
_controller->parentController()->hideLayer();
|
||||||
|
close();
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WrapWidget::addTopBarMenuButton() {
|
void WrapWidget::addTopBarMenuButton() {
|
||||||
|
@ -438,7 +440,7 @@ void WrapWidget::addTopBarMenuButton() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WrapWidget::closeByOutsideClick() const {
|
bool WrapWidget::closeByOutsideClick() const {
|
||||||
return true;
|
return _content->closeByOutsideClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WrapWidget::addProfileCallsButton() {
|
void WrapWidget::addProfileCallsButton() {
|
||||||
|
@ -872,8 +874,12 @@ void WrapWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) {
|
if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Back) {
|
||||||
if (hasStackHistory() || wrap() != Wrap::Layer) {
|
if (hasStackHistory() || wrap() != Wrap::Layer) {
|
||||||
checkBeforeClose([=] { _controller->showBackFromStack(); });
|
checkBeforeClose([=] { _controller->showBackFromStack(); });
|
||||||
return;
|
} else {
|
||||||
|
checkBeforeClose([=] {
|
||||||
|
_controller->parentController()->hideSpecialLayer();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
SectionWidget::keyPressEvent(e);
|
SectionWidget::keyPressEvent(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,6 +232,14 @@ rpl::producer<bool> Widget::desiredShadowVisibility() const {
|
||||||
: rpl::single(true);
|
: rpl::single(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Widget::closeByOutsideClick() const {
|
||||||
|
return _inner->closeByOutsideClick();;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::checkBeforeClose(Fn<void()> close) {
|
||||||
|
_inner->checkBeforeClose(std::move(close));
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<QString> Widget::title() {
|
rpl::producer<QString> Widget::title() {
|
||||||
return _inner->title();
|
return _inner->title();
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,8 @@ public:
|
||||||
|
|
||||||
rpl::producer<bool> desiredShadowVisibility() const override;
|
rpl::producer<bool> desiredShadowVisibility() const override;
|
||||||
|
|
||||||
|
bool closeByOutsideClick() const override;
|
||||||
|
void checkBeforeClose(Fn<void()> close) override;
|
||||||
rpl::producer<QString> title() override;
|
rpl::producer<QString> title() override;
|
||||||
|
|
||||||
void enableBackButton() override;
|
void enableBackButton() override;
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
not_null<Window::SessionController*> controller);
|
not_null<Window::SessionController*> controller);
|
||||||
~AwayMessage();
|
~AwayMessage();
|
||||||
|
|
||||||
|
[[nodiscard]] bool closeByOutsideClick() const override;
|
||||||
[[nodiscard]] rpl::producer<QString> title() override;
|
[[nodiscard]] rpl::producer<QString> title() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -199,6 +200,10 @@ AwayMessage::~AwayMessage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AwayMessage::closeByOutsideClick() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<QString> AwayMessage::title() {
|
rpl::producer<QString> AwayMessage::title() {
|
||||||
return tr::lng_away_title();
|
return tr::lng_away_title();
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
not_null<Window::SessionController*> controller);
|
not_null<Window::SessionController*> controller);
|
||||||
~Chatbots();
|
~Chatbots();
|
||||||
|
|
||||||
|
[[nodiscard]] bool closeByOutsideClick() const override;
|
||||||
[[nodiscard]] rpl::producer<QString> title() override;
|
[[nodiscard]] rpl::producer<QString> title() override;
|
||||||
|
|
||||||
const Ui::RoundRect *bottomSkipRounding() const override {
|
const Ui::RoundRect *bottomSkipRounding() const override {
|
||||||
|
@ -380,6 +381,10 @@ Chatbots::~Chatbots() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Chatbots::closeByOutsideClick() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<QString> Chatbots::title() {
|
rpl::producer<QString> Chatbots::title() {
|
||||||
return tr::lng_chatbots_title();
|
return tr::lng_chatbots_title();
|
||||||
}
|
}
|
||||||
|
@ -402,7 +407,7 @@ void Chatbots::setupContent(
|
||||||
.about = tr::lng_chatbots_about(
|
.about = tr::lng_chatbots_about(
|
||||||
lt_link,
|
lt_link,
|
||||||
tr::lng_chatbots_about_link(
|
tr::lng_chatbots_about_link(
|
||||||
) | Ui::Text::ToLink(u"internal:about_business_chatbots"_q),
|
) | Ui::Text::ToLink(tr::lng_chatbots_info_url(tr::now)),
|
||||||
Ui::Text::WithEntities),
|
Ui::Text::WithEntities),
|
||||||
.aboutMargins = st::peerAppearanceCoverLabelMargin,
|
.aboutMargins = st::peerAppearanceCoverLabelMargin,
|
||||||
});
|
});
|
||||||
|
@ -485,7 +490,7 @@ void Chatbots::save() {
|
||||||
.recipients = _recipients.current(),
|
.recipients = _recipients.current(),
|
||||||
.repliesAllowed = _repliesAllowed.current(),
|
.repliesAllowed = _repliesAllowed.current(),
|
||||||
}, [=] {
|
}, [=] {
|
||||||
}, [=](QString error) { show->showToast(error); });
|
}, fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
not_null<Window::SessionController*> controller);
|
not_null<Window::SessionController*> controller);
|
||||||
~Greeting();
|
~Greeting();
|
||||||
|
|
||||||
|
[[nodiscard]] bool closeByOutsideClick() const override;
|
||||||
[[nodiscard]] rpl::producer<QString> title() override;
|
[[nodiscard]] rpl::producer<QString> title() override;
|
||||||
|
|
||||||
const Ui::RoundRect *bottomSkipRounding() const override {
|
const Ui::RoundRect *bottomSkipRounding() const override {
|
||||||
|
@ -105,6 +106,10 @@ Greeting::~Greeting() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Greeting::closeByOutsideClick() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<QString> Greeting::title() {
|
rpl::producer<QString> Greeting::title() {
|
||||||
return tr::lng_greeting_title();
|
return tr::lng_greeting_title();
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,8 +168,10 @@ void AddBusinessRecipientsSelector(
|
||||||
modify(now);
|
modify(now);
|
||||||
*data = std::move(now);
|
*data = std::move(now);
|
||||||
};
|
};
|
||||||
|
const auto ¤t = data->current();
|
||||||
|
const auto all = current.allButExcluded || current.included.empty();
|
||||||
const auto group = std::make_shared<Ui::RadiobuttonGroup>(
|
const auto group = std::make_shared<Ui::RadiobuttonGroup>(
|
||||||
data->current().allButExcluded ? kAllExcept : kSelectedOnly);
|
all ? kAllExcept : kSelectedOnly);
|
||||||
const auto everyone = container->add(
|
const auto everyone = container->add(
|
||||||
object_ptr<Ui::Radiobutton>(
|
object_ptr<Ui::Radiobutton>(
|
||||||
container,
|
container,
|
||||||
|
@ -281,6 +283,12 @@ void AddBusinessRecipientsSelector(
|
||||||
}, lifetime);
|
}, lifetime);
|
||||||
|
|
||||||
SetupBusinessChatsPreview(includeInner, included);
|
SetupBusinessChatsPreview(includeInner, included);
|
||||||
|
included->value(
|
||||||
|
) | rpl::start_with_next([=](const Data::BusinessChats &value) {
|
||||||
|
if (value.empty() && group->current() == kSelectedOnly) {
|
||||||
|
group->setValue(kAllExcept);
|
||||||
|
}
|
||||||
|
}, lifetime);
|
||||||
|
|
||||||
includeWrap->toggleOn(data->value(
|
includeWrap->toggleOn(data->value(
|
||||||
) | rpl::map([](const Data::BusinessRecipients &value) {
|
) | rpl::map([](const Data::BusinessRecipients &value) {
|
||||||
|
@ -289,6 +297,20 @@ void AddBusinessRecipientsSelector(
|
||||||
includeWrap->finishAnimating();
|
includeWrap->finishAnimating();
|
||||||
|
|
||||||
group->setChangedCallback([=](int value) {
|
group->setChangedCallback([=](int value) {
|
||||||
|
if (value == kSelectedOnly && data->current().included.empty()) {
|
||||||
|
group->setValue(kAllExcept);
|
||||||
|
const auto save = [=](Data::BusinessChats value) {
|
||||||
|
change([&](Data::BusinessRecipients &data) {
|
||||||
|
data.included = std::move(value);
|
||||||
|
});
|
||||||
|
group->setValue(kSelectedOnly);
|
||||||
|
};
|
||||||
|
EditBusinessChats(controller, {
|
||||||
|
.save = crl::guard(includeAdd, save),
|
||||||
|
.include = true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
change([&](Data::BusinessRecipients &data) {
|
change([&](Data::BusinessRecipients &data) {
|
||||||
data.allButExcluded = (value == kAllExcept);
|
data.allButExcluded = (value == kAllExcept);
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
not_null<Window::SessionController*> controller);
|
not_null<Window::SessionController*> controller);
|
||||||
~WorkingHours();
|
~WorkingHours();
|
||||||
|
|
||||||
|
[[nodiscard]] bool closeByOutsideClick() const override;
|
||||||
[[nodiscard]] rpl::producer<QString> title() override;
|
[[nodiscard]] rpl::producer<QString> title() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -529,6 +530,10 @@ WorkingHours::~WorkingHours() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WorkingHours::closeByOutsideClick() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<QString> WorkingHours::title() {
|
rpl::producer<QString> WorkingHours::title() {
|
||||||
return tr::lng_hours_title();
|
return tr::lng_hours_title();
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,12 @@ public:
|
||||||
[[nodiscard]] virtual rpl::producer<std::vector<Type>> removeFromStack() {
|
[[nodiscard]] virtual rpl::producer<std::vector<Type>> removeFromStack() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] virtual bool closeByOutsideClick() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual void checkBeforeClose(Fn<void()> close) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
[[nodiscard]] virtual rpl::producer<QString> title() = 0;
|
[[nodiscard]] virtual rpl::producer<QString> title() = 0;
|
||||||
virtual void sectionSaveChanges(FnMut<void()> done) {
|
virtual void sectionSaveChanges(FnMut<void()> done) {
|
||||||
done();
|
done();
|
||||||
|
|
Loading…
Reference in New Issue