mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Improve filters save-on-demand.
This commit is contained in:
parent
06cf2b562f
commit
292e5bc3f7
5 changed files with 129 additions and 38 deletions
|
@ -3560,6 +3560,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_filters_menu_add" = "Add to folder";
|
||||
"lng_filters_toast_add" = "{chat} added to {folder} folder";
|
||||
"lng_filters_toast_remove" = "{chat} removed from {folder} folder";
|
||||
"lng_filters_shareable_status" = "shareable folder";
|
||||
|
||||
"lng_filters_delete_sure" = "Are you sure you want to delete this folder? This will also deactivate all the invite links used to share this folder.";
|
||||
"lng_filters_link" = "Share Folder";
|
||||
|
|
|
@ -540,27 +540,18 @@ void EditFilterBox(
|
|||
Fn<void(Data::ChatFilter)> next)> saveAnd) {
|
||||
using namespace rpl::mappers;
|
||||
|
||||
const auto creating = filter.title().isEmpty();
|
||||
box->setWidth(st::boxWideWidth);
|
||||
box->setTitle(creating ? tr::lng_filters_new() : tr::lng_filters_edit());
|
||||
box->setCloseByOutsideClick(false);
|
||||
|
||||
Data::AmPremiumValue(
|
||||
&window->session()
|
||||
) | rpl::start_with_next([=] {
|
||||
box->closeBox();
|
||||
}, box->lifetime());
|
||||
|
||||
struct State {
|
||||
rpl::variable<Data::ChatFilter> rules;
|
||||
rpl::variable<std::vector<Data::ChatFilterLink>> links;
|
||||
rpl::variable<bool> hasLinks;
|
||||
rpl::variable<bool> chatlist;
|
||||
rpl::variable<bool> creating;
|
||||
};
|
||||
const auto owner = &window->session().data();
|
||||
const auto state = box->lifetime().make_state<State>(State{
|
||||
.rules = filter,
|
||||
.chatlist = filter.chatlist(),
|
||||
.creating = filter.title().isEmpty(),
|
||||
});
|
||||
state->links = owner->chatsFilters().chatlistLinks(filter.id()),
|
||||
state->hasLinks = state->links.value() | rpl::map([=](const auto &v) {
|
||||
|
@ -573,6 +564,32 @@ void EditFilterBox(
|
|||
}
|
||||
const auto data = &state->rules;
|
||||
|
||||
owner->chatsFilters().isChatlistChanged(
|
||||
) | rpl::filter([=](FilterId id) {
|
||||
return (id == data->current().id());
|
||||
}) | rpl::start_with_next([=](FilterId id) {
|
||||
const auto filters = &owner->chatsFilters();
|
||||
const auto &list = filters->list();
|
||||
const auto i = ranges::find(list, id, &Data::ChatFilter::id);
|
||||
if (i == end(list)) {
|
||||
return;
|
||||
}
|
||||
*data = data->current().withChatlist(i->chatlist(), i->hasMyLinks());
|
||||
}, box->lifetime());
|
||||
|
||||
box->setWidth(st::boxWideWidth);
|
||||
box->setTitle(rpl::conditional(
|
||||
state->creating.value(),
|
||||
tr::lng_filters_new(),
|
||||
tr::lng_filters_edit()));
|
||||
box->setCloseByOutsideClick(false);
|
||||
|
||||
Data::AmPremiumValue(
|
||||
&window->session()
|
||||
) | rpl::start_with_next([=] {
|
||||
box->closeBox();
|
||||
}, box->lifetime());
|
||||
|
||||
const auto content = box->verticalLayout();
|
||||
const auto name = content->add(
|
||||
object_ptr<Ui::InputField>(
|
||||
|
@ -592,7 +609,12 @@ void EditFilterBox(
|
|||
|
||||
const auto nameEditing = box->lifetime().make_state<NameEditing>(
|
||||
NameEditing{ name });
|
||||
nameEditing->custom = !creating;
|
||||
|
||||
state->creating.value(
|
||||
) | rpl::filter(!_1) | rpl::start_with_next([=] {
|
||||
nameEditing->custom = true;
|
||||
}, box->lifetime());
|
||||
|
||||
QObject::connect(name, &Ui::InputField::changed, [=] {
|
||||
if (!nameEditing->settingDefault) {
|
||||
nameEditing->custom = true;
|
||||
|
@ -683,14 +705,6 @@ void EditFilterBox(
|
|||
const auto collect = [=]() -> std::optional<Data::ChatFilter> {
|
||||
const auto title = name->getLastText().trimmed();
|
||||
const auto rules = data->current();
|
||||
const auto result = Data::ChatFilter(
|
||||
rules.id(),
|
||||
title,
|
||||
rules.iconEmoji(),
|
||||
rules.flags(),
|
||||
rules.always(),
|
||||
rules.pinned(),
|
||||
rules.never());
|
||||
if (title.isEmpty()) {
|
||||
name->showError();
|
||||
box->scrollToY(0);
|
||||
|
@ -704,7 +718,7 @@ void EditFilterBox(
|
|||
window->window().showToast(tr::lng_filters_default(tr::now));
|
||||
return {};
|
||||
}
|
||||
return result;
|
||||
return rules.withTitle(title);
|
||||
};
|
||||
|
||||
AddSubsectionTitle(
|
||||
|
@ -758,8 +772,7 @@ void EditFilterBox(
|
|||
return;
|
||||
}
|
||||
saveAnd(*result, crl::guard(box, [=](Data::ChatFilter updated) {
|
||||
box->setTitle(tr::lng_filters_edit());
|
||||
nameEditing->custom = true;
|
||||
state->creating = false;
|
||||
|
||||
// Comparison of ChatFilter-s don't take id into account!
|
||||
data->force_assign(updated);
|
||||
|
@ -768,6 +781,7 @@ void EditFilterBox(
|
|||
ExportFilterLink(id, shared, [=](Data::ChatFilterLink link) {
|
||||
Expects(link.id == id);
|
||||
|
||||
*data = data->current().withChatlist(true, true);
|
||||
window->show(ShowLinkBox(window, updated, link));
|
||||
}, [=](QString error) {
|
||||
if (error == u"CHATLISTS_TOO_MUCH"_q) {
|
||||
|
@ -826,9 +840,11 @@ void EditFilterBox(
|
|||
}
|
||||
};
|
||||
|
||||
box->addButton(
|
||||
creating ? tr::lng_filters_create_button() : tr::lng_settings_save(),
|
||||
save);
|
||||
box->addButton(rpl::conditional(
|
||||
state->creating.value(),
|
||||
tr::lng_filters_create_button(),
|
||||
tr::lng_settings_save()
|
||||
), save);
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,27 @@ ChatFilter ChatFilter::withId(FilterId id) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
ChatFilter ChatFilter::withTitle(const QString &title) const {
|
||||
auto result = *this;
|
||||
result._title = title;
|
||||
return result;
|
||||
}
|
||||
|
||||
ChatFilter ChatFilter::withChatlist(bool chatlist, bool hasMyLinks) const {
|
||||
auto result = *this;
|
||||
if (chatlist) {
|
||||
result._flags |= Flag::Chatlist;
|
||||
if (hasMyLinks) {
|
||||
result._flags |= Flag::HasMyLinks;
|
||||
} else {
|
||||
result._flags &= ~Flag::HasMyLinks;
|
||||
}
|
||||
} else {
|
||||
result._flags &= ~(Flag::Chatlist | Flag::HasMyLinks);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MTPDialogFilter ChatFilter::tl(FilterId replaceId) const {
|
||||
auto always = _always;
|
||||
auto pinned = QVector<MTPInputPeer>();
|
||||
|
@ -582,16 +603,22 @@ void ChatFilters::applyRemove(int position) {
|
|||
bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) {
|
||||
Expects(filter.id() == updated.id());
|
||||
|
||||
using Flag = ChatFilter::Flag;
|
||||
|
||||
const auto id = filter.id();
|
||||
const auto exceptionsChanged = filter.always() != updated.always();
|
||||
const auto rulesMask = ~(Flag::Chatlist | Flag::HasMyLinks);
|
||||
const auto rulesChanged = exceptionsChanged
|
||||
|| (filter.flags() != updated.flags())
|
||||
|| ((filter.flags() & rulesMask) != (updated.flags() & rulesMask))
|
||||
|| (filter.never() != updated.never());
|
||||
const auto pinnedChanged = (filter.pinned() != updated.pinned());
|
||||
if (!rulesChanged
|
||||
&& !pinnedChanged
|
||||
&& filter.title() == updated.title()
|
||||
&& filter.iconEmoji() == updated.iconEmoji()) {
|
||||
const auto chatlistChanged = (filter.chatlist() != updated.chatlist())
|
||||
|| (filter.hasMyLinks() != updated.hasMyLinks());
|
||||
const auto listUpdated = rulesChanged
|
||||
|| pinnedChanged
|
||||
|| (filter.title() != updated.title())
|
||||
|| (filter.iconEmoji() != updated.iconEmoji());
|
||||
if (!listUpdated && !chatlistChanged) {
|
||||
return false;
|
||||
}
|
||||
if (rulesChanged) {
|
||||
|
@ -630,7 +657,10 @@ bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) {
|
|||
const auto filterList = _owner->chatsFilters().chatsList(id);
|
||||
filterList->pinned()->applyList(filter.pinned());
|
||||
}
|
||||
return true;
|
||||
if (chatlistChanged) {
|
||||
_isChatlistChanged.fire_copy(id);
|
||||
}
|
||||
return listUpdated;
|
||||
}
|
||||
|
||||
bool ChatFilters::applyOrder(const QVector<MTPint> &order) {
|
||||
|
@ -767,6 +797,10 @@ rpl::producer<> ChatFilters::changed() const {
|
|||
return _listChanged.events();
|
||||
}
|
||||
|
||||
rpl::producer<FilterId> ChatFilters::isChatlistChanged() const {
|
||||
return _isChatlistChanged.events();
|
||||
}
|
||||
|
||||
bool ChatFilters::loadNextExceptions(bool chatsListLoaded) {
|
||||
if (_exceptionsLoadRequestId) {
|
||||
return true;
|
||||
|
|
|
@ -54,6 +54,10 @@ public:
|
|||
base::flat_set<not_null<History*>> never);
|
||||
|
||||
[[nodiscard]] ChatFilter withId(FilterId id) const;
|
||||
[[nodiscard]] ChatFilter withTitle(const QString &title) const;
|
||||
[[nodiscard]] ChatFilter withChatlist(
|
||||
bool chatlist,
|
||||
bool hasMyLinks) const;
|
||||
|
||||
[[nodiscard]] static ChatFilter FromTL(
|
||||
const MTPDialogFilter &data,
|
||||
|
@ -126,6 +130,7 @@ public:
|
|||
void moveAllToFront();
|
||||
[[nodiscard]] const std::vector<ChatFilter> &list() const;
|
||||
[[nodiscard]] rpl::producer<> changed() const;
|
||||
[[nodiscard]] rpl::producer<FilterId> isChatlistChanged() const;
|
||||
[[nodiscard]] bool loaded() const;
|
||||
[[nodiscard]] bool has() const;
|
||||
|
||||
|
@ -195,6 +200,7 @@ private:
|
|||
std::vector<ChatFilter> _list;
|
||||
base::flat_map<FilterId, std::unique_ptr<Dialogs::MainList>> _chatsLists;
|
||||
rpl::event_stream<> _listChanged;
|
||||
rpl::event_stream<FilterId> _isChatlistChanged;
|
||||
mtpRequestId _loadRequestId = 0;
|
||||
mtpRequestId _saveOrderRequestId = 0;
|
||||
mtpRequestId _saveOrderAfterId = 0;
|
||||
|
|
|
@ -159,7 +159,9 @@ struct FilterRow {
|
|||
? tr::lng_filters_chats_count(tr::now, lt_count_short, count)
|
||||
: tr::lng_filters_no_chats(tr::now);
|
||||
return filter.chatlist()
|
||||
? result + QString::fromUtf8(" \xE2\x80\xA2 shareable folder")
|
||||
? (result
|
||||
+ QString::fromUtf8(" \xE2\x80\xA2 ")
|
||||
+ tr::lng_filters_shareable_status(tr::now))
|
||||
: result;
|
||||
}
|
||||
|
||||
|
@ -468,9 +470,7 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
|
|||
const auto saveAnd = [=](
|
||||
const Data::ChatFilter &data,
|
||||
Fn<void(Data::ChatFilter)> next) {
|
||||
const auto found = find(button);
|
||||
found->filter = data;
|
||||
button->updateData(data);
|
||||
doneCallback(data);
|
||||
state->save(button, next);
|
||||
};
|
||||
controller->window().show(Box(
|
||||
|
@ -526,6 +526,21 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
session->data().chatsFilters().isChatlistChanged(
|
||||
) | rpl::start_with_next([=](FilterId id) {
|
||||
const auto filters = &session->data().chatsFilters();
|
||||
const auto &list = filters->list();
|
||||
const auto i = ranges::find(list, id, &Data::ChatFilter::id);
|
||||
const auto j = ranges::find(state->rows, id, [](const auto &row) {
|
||||
return row.filter.id();
|
||||
});
|
||||
if (i == end(list) || j == end(state->rows)) {
|
||||
return;
|
||||
}
|
||||
j->filter = j->filter.withChatlist(i->chatlist(), i->hasMyLinks());
|
||||
j->button->updateCount(j->filter);
|
||||
}, container->lifetime());
|
||||
|
||||
AddButton(
|
||||
container,
|
||||
tr::lng_filters_create(),
|
||||
|
@ -535,13 +550,20 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
|
|||
if (showLimitReached()) {
|
||||
return;
|
||||
}
|
||||
const auto created = std::make_shared<FilterRowButton*>(nullptr);
|
||||
const auto doneCallback = [=](const Data::ChatFilter &result) {
|
||||
addFilter(result);
|
||||
if (const auto button = *created) {
|
||||
find(button)->filter = result;
|
||||
button->updateData(result);
|
||||
} else {
|
||||
*created = addFilter(result);
|
||||
}
|
||||
};
|
||||
const auto saveAnd = [=](
|
||||
const Data::ChatFilter &data,
|
||||
Fn<void(Data::ChatFilter)> next) {
|
||||
state->save(addFilter(data), next);
|
||||
doneCallback(data);
|
||||
state->save(*created, next);
|
||||
};
|
||||
controller->window().show(Box(
|
||||
EditFilterBox,
|
||||
|
@ -715,6 +737,18 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
order.insert(order.begin() + position, FilterId(0));
|
||||
}
|
||||
if (next) {
|
||||
// We're not closing the layer yet, so delete removed rows.
|
||||
for (auto i = state->rows.begin(); i != state->rows.end();) {
|
||||
if (i->removed) {
|
||||
const auto button = i->button;
|
||||
i = state->rows.erase(i);
|
||||
delete button;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
crl::on_main(session, [
|
||||
session,
|
||||
next,
|
||||
|
|
Loading…
Add table
Reference in a new issue