Added quick actions for folders to menu from chats list.

This commit is contained in:
23rd 2022-04-05 23:51:42 +03:00
parent eabe7a3411
commit d224b3d301
5 changed files with 249 additions and 4 deletions

View File

@ -216,6 +216,8 @@ PRIVATE
boxes/background_preview_box.h
boxes/change_phone_box.cpp
boxes/change_phone_box.h
boxes/choose_filter_box.cpp
boxes/choose_filter_box.h
boxes/connection_box.cpp
boxes/connection_box.h
boxes/create_poll_box.cpp

View File

@ -3082,6 +3082,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_filters_context_remove" = "Remove";
"lng_filters_remove_sure" = "This will remove the folder, your chats will not be deleted.";
"lng_filters_remove_yes" = "Remove";
"lng_filters_menu_add" = "Add to folder";
"lng_filters_menu_remove" = "Remove from folder";
"lng_filters_add_box_title" = "Add to...";
"lng_chat_theme_change" = "Change colors";
"lng_chat_theme_none" = "No\nTheme";

View File

@ -0,0 +1,184 @@
/*
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"
#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"
#include "ui/layers/generic_box.h"
#include "ui/widgets/buttons.h"
#include "styles/style_settings.h"
#include "styles/style_payments.h" // paymentsSectionButton
namespace {
class FolderButton : public Ui::SettingsButton {
public:
FolderButton(
not_null<Ui::RpWidget*> parent,
const Data::ChatFilter &filter);
protected:
void paintEvent(QPaintEvent *e) override;
private:
const Ui::FilterIcon _icon;
};
FolderButton::FolderButton(
not_null<Ui::RpWidget*> parent,
const Data::ChatFilter &filter)
: SettingsButton(
parent,
rpl::single(filter.title()),
st::paymentsSectionButton)
, _icon(Ui::ComputeFilterIcon(filter)) {
}
void FolderButton::paintEvent(QPaintEvent *e) {
SettingsButton::paintEvent(e);
Painter p(this);
const auto over = isOver() || isDown();
const auto icon = Ui::LookupFilterIcon(_icon).normal;
icon->paint(
p,
st::settingsFilterIconLeft,
(height() - icon->height()) / 2,
width(),
(over
? st::dialogsUnreadBgMutedOver
: st::dialogsUnreadBgMuted)->c);
}
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) {
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()
)).fail([=](const MTP::Error &error) {
// 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()) {
if (!filter.contains(_history)) {
return true;
}
}
return false;
}
bool ChooseFilterValidator::canRemove(FilterId filterId) const {
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;
}
void ChooseFilterValidator::add(FilterId filterId) const {
ChangeFilterById(filterId, _history, true);
}
void ChooseFilterValidator::remove(FilterId filterId) const {
ChangeFilterById(filterId, _history, false);
}
void ChooseFilterBox(
not_null<Ui::GenericBox*> box,
not_null<History*> history) {
box->setTitle(tr::lng_filters_add_box_title());
const auto validator = ChooseFilterValidator(history);
const auto container = box->verticalLayout()->add(
object_ptr<Ui::VerticalLayout>(box->verticalLayout()));
const auto rebuild = [=] {
while (container->count()) {
delete container->widgetAt(0);
}
for (const auto &filter : history->owner().chatsFilters().list()) {
if (filter.contains(history)) {
continue;
}
container->add(
object_ptr<FolderButton>(box, filter),
style::margins()
)->setClickedCallback([=, id = filter.id()] {
validator.add(id);
box->closeBox();
});
}
container->resizeToWidth(box->verticalLayout()->width());
if (!container->count()) {
box->closeBox();
}
};
history->owner().chatsFilters().changed(
) | rpl::start_with_next([=] {
rebuild();
}, box->lifetime());
rebuild();
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
}

View File

@ -0,0 +1,33 @@
/*
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
*/
#pragma once
namespace Ui {
class GenericBox;
} // namespace Ui
class History;
class ChooseFilterValidator final {
public:
ChooseFilterValidator(not_null<History*> history);
[[nodiscard]] bool canAdd() const;
[[nodiscard]] bool canRemove(FilterId filterId) const;
void add(FilterId filterId) const;
void remove(FilterId filterId) const;
private:
const not_null<History*> _history;
};
void ChooseFilterBox(
not_null<Ui::GenericBox*> box,
not_null<History*> history);

View File

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/max_invite_box.h"
#include "boxes/mute_settings_box.h"
#include "boxes/add_contact_box.h"
#include "boxes/choose_filter_box.h"
#include "boxes/create_poll_box.h"
#include "boxes/pin_messages_box.h"
#include "boxes/peers/add_bot_to_chat_box.h"
@ -180,7 +181,7 @@ private:
void addToggleMuteSubmenu(bool addSeparator);
void addSupportInfo();
void addInfo();
//void addToFolder();
void addToggleFolder();
void addToggleUnreadMark();
void addToggleArchive();
void addClearHistory();
@ -425,8 +426,30 @@ void Filler::addInfo() {
}, peer->isUser() ? &st::menuIconProfile : &st::menuIconInfo);
}
//void Filler::addToFolder() {
//}
void Filler::addToggleFolder() {
const auto history = _request.key.history();
if (!history) {
return;
}
if (!_request.filterId) {
if (!ChooseFilterValidator(history).canAdd()) {
return;
}
const auto window = _controller;
_addAction(tr::lng_filters_menu_add(tr::now), [=] {
window->show(Box(ChooseFilterBox, history));
}, nullptr);
} else {
const auto id = _request.filterId;
const auto validator = ChooseFilterValidator(history);
if (!validator.canRemove(id)) {
return;
}
_addAction(tr::lng_filters_menu_remove(tr::now), [=] {
validator.remove(id);
}, nullptr);
}
}
void Filler::addToggleUnreadMark() {
const auto peer = _peer;
@ -817,7 +840,7 @@ void Filler::fillChatsListActions() {
}
addToggleMuteSubmenu(false);
addToggleUnreadMark();
// addToFolder();
addToggleFolder();
if (const auto user = _peer->asUser()) {
if (!user->isContact()) {
addBlockUser();