2022-04-05 20:51:42 +00:00
|
|
|
/*
|
|
|
|
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/choose_filter_box.h"
|
|
|
|
|
|
|
|
#include "apiwrap.h"
|
2022-05-09 13:09:46 +00:00
|
|
|
#include "boxes/premium_limits_box.h"
|
2022-04-05 20:51:42 +00:00
|
|
|
#include "core/application.h" // primaryWindow
|
2022-04-05 20:51:42 +00:00
|
|
|
#include "data/data_chat_filters.h"
|
|
|
|
#include "data/data_session.h"
|
|
|
|
#include "history/history.h"
|
|
|
|
#include "lang/lang_keys.h"
|
|
|
|
#include "main/main_session.h"
|
|
|
|
#include "ui/filter_icons.h"
|
2022-04-05 20:51:42 +00:00
|
|
|
#include "ui/text/text_utilities.h" // Ui::Text::Bold
|
|
|
|
#include "ui/toast/toast.h"
|
2022-04-05 20:51:42 +00:00
|
|
|
#include "ui/widgets/buttons.h"
|
2022-04-10 10:49:14 +00:00
|
|
|
#include "ui/widgets/popup_menu.h"
|
2022-04-05 20:51:42 +00:00
|
|
|
#include "window/window_session_controller.h"
|
2022-04-05 20:51:42 +00:00
|
|
|
#include "styles/style_settings.h"
|
|
|
|
#include "styles/style_payments.h" // paymentsSectionButton
|
2022-04-10 10:49:14 +00:00
|
|
|
#include "styles/style_media_player.h" // mediaPlayerMenuCheck
|
2022-04-05 20:51:42 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
Data::ChatFilter ChangedFilter(
|
|
|
|
const Data::ChatFilter &filter,
|
|
|
|
not_null<History*> history,
|
|
|
|
bool add) {
|
|
|
|
auto always = base::duplicate(filter.always());
|
|
|
|
if (add) {
|
|
|
|
always.insert(history);
|
|
|
|
} else {
|
|
|
|
always.remove(history);
|
|
|
|
}
|
|
|
|
auto never = base::duplicate(filter.never());
|
|
|
|
if (add) {
|
|
|
|
never.remove(history);
|
|
|
|
} else {
|
|
|
|
never.insert(history);
|
|
|
|
}
|
|
|
|
return Data::ChatFilter(
|
|
|
|
filter.id(),
|
|
|
|
filter.title(),
|
|
|
|
filter.iconEmoji(),
|
|
|
|
filter.flags(),
|
|
|
|
std::move(always),
|
|
|
|
filter.pinned(),
|
|
|
|
std::move(never));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ChangeFilterById(
|
|
|
|
FilterId filterId,
|
|
|
|
not_null<History*> history,
|
|
|
|
bool add) {
|
2022-05-17 09:24:35 +00:00
|
|
|
Expects(filterId != 0);
|
|
|
|
|
2022-04-05 20:51:42 +00:00
|
|
|
const auto list = history->owner().chatsFilters().list();
|
|
|
|
const auto i = ranges::find(list, filterId, &Data::ChatFilter::id);
|
|
|
|
if (i != end(list)) {
|
|
|
|
const auto was = *i;
|
|
|
|
const auto filter = ChangedFilter(was, history, add);
|
|
|
|
history->owner().chatsFilters().set(filter);
|
|
|
|
history->session().api().request(MTPmessages_UpdateDialogFilter(
|
|
|
|
MTP_flags(MTPmessages_UpdateDialogFilter::Flag::f_filter),
|
|
|
|
MTP_int(filter.id()),
|
|
|
|
filter.tl()
|
2022-08-09 11:12:19 +00:00
|
|
|
)).done([=, chat = history->peer->name(), name = filter.title()]{
|
2022-04-05 20:51:42 +00:00
|
|
|
// Since only the primary window has dialogs list,
|
|
|
|
// We can safely show toast there.
|
|
|
|
if (const auto controller = Core::App().primaryWindow()) {
|
|
|
|
auto text = (add
|
|
|
|
? tr::lng_filters_toast_add
|
|
|
|
: tr::lng_filters_toast_remove)(
|
|
|
|
tr::now,
|
|
|
|
lt_chat,
|
|
|
|
Ui::Text::Bold(chat),
|
|
|
|
lt_folder,
|
2022-08-09 11:12:19 +00:00
|
|
|
Ui::Text::Bold(name),
|
2022-04-05 20:51:42 +00:00
|
|
|
Ui::Text::WithEntities);
|
|
|
|
Ui::Toast::Show(
|
|
|
|
Window::Show(controller).toastParent(),
|
|
|
|
{ .text = std::move(text), .st = &st::defaultToast });
|
|
|
|
}
|
|
|
|
}).fail([=](const MTP::Error &error) {
|
2022-04-05 20:51:42 +00:00
|
|
|
// Revert filter on fail.
|
|
|
|
history->owner().chatsFilters().set(was);
|
|
|
|
}).send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
ChooseFilterValidator::ChooseFilterValidator(not_null<History*> history)
|
|
|
|
: _history(history) {
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ChooseFilterValidator::canAdd() const {
|
|
|
|
for (const auto &filter : _history->owner().chatsFilters().list()) {
|
2022-05-17 09:24:35 +00:00
|
|
|
if (filter.id() && !filter.contains(_history)) {
|
2022-04-05 20:51:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ChooseFilterValidator::canRemove(FilterId filterId) const {
|
2022-05-17 09:24:35 +00:00
|
|
|
Expects(filterId != 0);
|
|
|
|
|
2022-04-05 20:51:42 +00:00
|
|
|
const auto list = _history->owner().chatsFilters().list();
|
|
|
|
const auto i = ranges::find(list, filterId, &Data::ChatFilter::id);
|
|
|
|
if (i != end(list)) {
|
|
|
|
const auto &filter = *i;
|
|
|
|
return filter.contains(_history)
|
|
|
|
&& ((filter.always().size() > 1) || filter.flags());
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-06-07 05:05:33 +00:00
|
|
|
ChooseFilterValidator::LimitData ChooseFilterValidator::limitReached(
|
|
|
|
FilterId filterId) const {
|
2022-05-17 09:24:35 +00:00
|
|
|
Expects(filterId != 0);
|
|
|
|
|
2022-05-09 13:09:46 +00:00
|
|
|
const auto list = _history->owner().chatsFilters().list();
|
|
|
|
const auto i = ranges::find(list, filterId, &Data::ChatFilter::id);
|
|
|
|
const auto limit = _history->owner().pinnedChatsLimit(nullptr, filterId);
|
2022-06-07 05:05:33 +00:00
|
|
|
return {
|
|
|
|
.reached = (i != end(list))
|
|
|
|
&& !ranges::contains(i->always(), _history)
|
|
|
|
&& (i->always().size() >= limit),
|
|
|
|
.count = int(i->always().size()),
|
|
|
|
};
|
2022-05-09 13:09:46 +00:00
|
|
|
}
|
|
|
|
|
2022-04-05 20:51:42 +00:00
|
|
|
void ChooseFilterValidator::add(FilterId filterId) const {
|
|
|
|
ChangeFilterById(filterId, _history, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ChooseFilterValidator::remove(FilterId filterId) const {
|
|
|
|
ChangeFilterById(filterId, _history, false);
|
|
|
|
}
|
|
|
|
|
2022-04-10 10:49:14 +00:00
|
|
|
void FillChooseFilterMenu(
|
2022-05-09 13:09:46 +00:00
|
|
|
not_null<Window::SessionController*> controller,
|
2022-04-10 10:49:14 +00:00
|
|
|
not_null<Ui::PopupMenu*> menu,
|
|
|
|
not_null<History*> history) {
|
2022-10-19 10:59:37 +00:00
|
|
|
const auto weak = base::make_weak(controller);
|
2022-04-10 10:49:14 +00:00
|
|
|
const auto validator = ChooseFilterValidator(history);
|
|
|
|
for (const auto &filter : history->owner().chatsFilters().list()) {
|
|
|
|
const auto id = filter.id();
|
2022-05-17 09:24:35 +00:00
|
|
|
if (!id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-04-10 10:49:14 +00:00
|
|
|
const auto contains = filter.contains(history);
|
|
|
|
const auto action = menu->addAction(filter.title(), [=] {
|
|
|
|
if (filter.contains(history)) {
|
|
|
|
if (validator.canRemove(id)) {
|
|
|
|
validator.remove(id);
|
|
|
|
}
|
2022-06-07 05:05:33 +00:00
|
|
|
} else if (const auto r = validator.limitReached(id); r.reached) {
|
|
|
|
controller->show(Box(
|
|
|
|
FilterChatsLimitBox,
|
|
|
|
&controller->session(),
|
|
|
|
r.count));
|
2022-05-09 13:09:46 +00:00
|
|
|
} else if (validator.canAdd()) {
|
|
|
|
validator.add(id);
|
2022-04-10 10:49:14 +00:00
|
|
|
}
|
|
|
|
}, contains ? &st::mediaPlayerMenuCheck : nullptr);
|
|
|
|
action->setEnabled(contains
|
|
|
|
? validator.canRemove(id)
|
|
|
|
: validator.canAdd());
|
|
|
|
}
|
|
|
|
history->owner().chatsFilters().changed(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
menu->hideMenu();
|
|
|
|
}, menu->lifetime());
|
|
|
|
}
|