mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Allow disabling animations in folder emoji.
This commit is contained in:
parent
c810005f86
commit
06341efe0d
17 changed files with 235 additions and 73 deletions
|
@ -5346,6 +5346,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_filters_edit" = "Edit Folder";
|
"lng_filters_edit" = "Edit Folder";
|
||||||
"lng_filters_setup_menu" = "Edit Folders";
|
"lng_filters_setup_menu" = "Edit Folders";
|
||||||
"lng_filters_new_name" = "Folder name";
|
"lng_filters_new_name" = "Folder name";
|
||||||
|
"lng_filters_enable_animations" = "Enable animations";
|
||||||
|
"lng_filters_disable_animations" = "Disable animations";
|
||||||
"lng_filters_add_chats" = "Add Chats";
|
"lng_filters_add_chats" = "Add Chats";
|
||||||
"lng_filters_remove_chats" = "Add Chats to Exclude";
|
"lng_filters_remove_chats" = "Add Chats to Exclude";
|
||||||
"lng_filters_include" = "Included chats";
|
"lng_filters_include" = "Included chats";
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
ToggleChatsController(
|
ToggleChatsController(
|
||||||
not_null<Window::SessionController*> window,
|
not_null<Window::SessionController*> window,
|
||||||
ToggleAction action,
|
ToggleAction action,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
std::vector<not_null<PeerData*>> chats,
|
std::vector<not_null<PeerData*>> chats,
|
||||||
std::vector<not_null<PeerData*>> additional);
|
std::vector<not_null<PeerData*>> additional);
|
||||||
|
|
||||||
|
@ -78,7 +78,6 @@ private:
|
||||||
Ui::RpWidget *_addedBottomWidget = nullptr;
|
Ui::RpWidget *_addedBottomWidget = nullptr;
|
||||||
|
|
||||||
ToggleAction _action = ToggleAction::Adding;
|
ToggleAction _action = ToggleAction::Adding;
|
||||||
TextWithEntities _filterTitle;
|
|
||||||
base::flat_set<not_null<PeerData*>> _checkable;
|
base::flat_set<not_null<PeerData*>> _checkable;
|
||||||
std::vector<not_null<PeerData*>> _chats;
|
std::vector<not_null<PeerData*>> _chats;
|
||||||
std::vector<not_null<PeerData*>> _additional;
|
std::vector<not_null<PeerData*>> _additional;
|
||||||
|
@ -141,7 +140,7 @@ void InitFilterLinkHeader(
|
||||||
not_null<PeerListBox*> box,
|
not_null<PeerListBox*> box,
|
||||||
Fn<void(int minHeight, int maxHeight, int addedTopHeight)> adjust,
|
Fn<void(int minHeight, int maxHeight, int addedTopHeight)> adjust,
|
||||||
Ui::FilterLinkHeaderType type,
|
Ui::FilterLinkHeaderType type,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
QString iconEmoji,
|
QString iconEmoji,
|
||||||
rpl::producer<int> count,
|
rpl::producer<int> count,
|
||||||
bool horizontalFilters) {
|
bool horizontalFilters) {
|
||||||
|
@ -149,18 +148,20 @@ void InitFilterLinkHeader(
|
||||||
Ui::LookupFilterIconByEmoji(
|
Ui::LookupFilterIconByEmoji(
|
||||||
iconEmoji
|
iconEmoji
|
||||||
).value_or(Ui::FilterIcon::Custom)).active;
|
).value_or(Ui::FilterIcon::Custom)).active;
|
||||||
|
const auto isStatic = title.isStatic;
|
||||||
const auto makeContext = [=](Fn<void()> repaint) {
|
const auto makeContext = [=](Fn<void()> repaint) {
|
||||||
return Core::MarkedTextContext{
|
return Core::MarkedTextContext{
|
||||||
.session = &box->peerListUiShow()->session(),
|
.session = &box->peerListUiShow()->session(),
|
||||||
.customEmojiRepaint = std::move(repaint),
|
.customEmojiRepaint = std::move(repaint),
|
||||||
|
.customEmojiLoopLimit = isStatic ? -1 : 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
auto header = Ui::MakeFilterLinkHeader(box, {
|
auto header = Ui::MakeFilterLinkHeader(box, {
|
||||||
.type = type,
|
.type = type,
|
||||||
.title = TitleText(type)(tr::now),
|
.title = TitleText(type)(tr::now),
|
||||||
.about = AboutText(type, title),
|
.about = AboutText(type, title.text),
|
||||||
.makeAboutContext = makeContext,
|
.makeAboutContext = makeContext,
|
||||||
.folderTitle = title,
|
.folderTitle = title.text,
|
||||||
.folderIcon = icon,
|
.folderIcon = icon,
|
||||||
.badge = (type == Ui::FilterLinkHeaderType::AddingChats
|
.badge = (type == Ui::FilterLinkHeaderType::AddingChats
|
||||||
? std::move(count)
|
? std::move(count)
|
||||||
|
@ -258,12 +259,11 @@ void ImportInvite(
|
||||||
ToggleChatsController::ToggleChatsController(
|
ToggleChatsController::ToggleChatsController(
|
||||||
not_null<Window::SessionController*> window,
|
not_null<Window::SessionController*> window,
|
||||||
ToggleAction action,
|
ToggleAction action,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
std::vector<not_null<PeerData*>> chats,
|
std::vector<not_null<PeerData*>> chats,
|
||||||
std::vector<not_null<PeerData*>> additional)
|
std::vector<not_null<PeerData*>> additional)
|
||||||
: _window(window)
|
: _window(window)
|
||||||
, _action(action)
|
, _action(action)
|
||||||
, _filterTitle(title)
|
|
||||||
, _chats(std::move(chats))
|
, _chats(std::move(chats))
|
||||||
, _additional(std::move(additional)) {
|
, _additional(std::move(additional)) {
|
||||||
setStyleOverrides(&st::filterLinkChatsList);
|
setStyleOverrides(&st::filterLinkChatsList);
|
||||||
|
@ -539,7 +539,7 @@ void ShowImportError(
|
||||||
|
|
||||||
void ShowImportToast(
|
void ShowImportToast(
|
||||||
base::weak_ptr<Window::SessionController> weak,
|
base::weak_ptr<Window::SessionController> weak,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
Ui::FilterLinkHeaderType type,
|
Ui::FilterLinkHeaderType type,
|
||||||
int added) {
|
int added) {
|
||||||
const auto strong = weak.get();
|
const auto strong = weak.get();
|
||||||
|
@ -551,7 +551,7 @@ void ShowImportToast(
|
||||||
? tr::lng_filters_added_title
|
? tr::lng_filters_added_title
|
||||||
: tr::lng_filters_updated_title;
|
: tr::lng_filters_updated_title;
|
||||||
auto text = Ui::Text::Wrapped(
|
auto text = Ui::Text::Wrapped(
|
||||||
phrase(tr::now, lt_folder, title, Ui::Text::WithEntities),
|
phrase(tr::now, lt_folder, title.text, Ui::Text::WithEntities),
|
||||||
EntityType::Bold);
|
EntityType::Bold);
|
||||||
if (added > 0) {
|
if (added > 0) {
|
||||||
const auto phrase = created
|
const auto phrase = created
|
||||||
|
@ -559,10 +559,12 @@ void ShowImportToast(
|
||||||
: tr::lng_filters_updated_also;
|
: tr::lng_filters_updated_also;
|
||||||
text.append('\n').append(phrase(tr::now, lt_count, added));
|
text.append('\n').append(phrase(tr::now, lt_count, added));
|
||||||
}
|
}
|
||||||
|
const auto isStatic = title.isStatic;
|
||||||
const auto makeContext = [=](not_null<QWidget*> widget) {
|
const auto makeContext = [=](not_null<QWidget*> widget) {
|
||||||
return Core::MarkedTextContext{
|
return Core::MarkedTextContext{
|
||||||
.session = &strong->session(),
|
.session = &strong->session(),
|
||||||
.customEmojiRepaint = [=] { widget->update(); },
|
.customEmojiRepaint = [=] { widget->update(); },
|
||||||
|
.customEmojiLoopLimit = isStatic ? -1 : 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
strong->showToast({
|
strong->showToast({
|
||||||
|
@ -595,7 +597,7 @@ void ProcessFilterInvite(
|
||||||
base::weak_ptr<Window::SessionController> weak,
|
base::weak_ptr<Window::SessionController> weak,
|
||||||
const QString &slug,
|
const QString &slug,
|
||||||
FilterId filterId,
|
FilterId filterId,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
QString iconEmoji,
|
QString iconEmoji,
|
||||||
std::vector<not_null<PeerData*>> peers,
|
std::vector<not_null<PeerData*>> peers,
|
||||||
std::vector<not_null<PeerData*>> already) {
|
std::vector<not_null<PeerData*>> already) {
|
||||||
|
@ -637,16 +639,18 @@ void ProcessFilterInvite(
|
||||||
|
|
||||||
raw->setRealContentHeight(box->heightValue());
|
raw->setRealContentHeight(box->heightValue());
|
||||||
|
|
||||||
|
const auto isStatic = title.isStatic;
|
||||||
const auto makeContext = [=](Fn<void()> update) {
|
const auto makeContext = [=](Fn<void()> update) {
|
||||||
return Core::MarkedTextContext{
|
return Core::MarkedTextContext{
|
||||||
.session = &strong->session(),
|
.session = &strong->session(),
|
||||||
.customEmojiRepaint = update,
|
.customEmojiRepaint = update,
|
||||||
|
.customEmojiLoopLimit = isStatic ? -1 : 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
auto owned = Ui::FilterLinkProcessButton(
|
auto owned = Ui::FilterLinkProcessButton(
|
||||||
box,
|
box,
|
||||||
type,
|
type,
|
||||||
title,
|
title.text,
|
||||||
makeContext,
|
makeContext,
|
||||||
std::move(badge));
|
std::move(badge));
|
||||||
|
|
||||||
|
@ -748,7 +752,7 @@ void CheckFilterInvite(
|
||||||
if (!strong) {
|
if (!strong) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto title = TextWithEntities();
|
auto title = Data::ChatFilterTitle();
|
||||||
auto iconEmoji = QString();
|
auto iconEmoji = QString();
|
||||||
auto filterId = FilterId();
|
auto filterId = FilterId();
|
||||||
auto peers = std::vector<not_null<PeerData*>>();
|
auto peers = std::vector<not_null<PeerData*>>();
|
||||||
|
@ -767,7 +771,8 @@ void CheckFilterInvite(
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
result.match([&](const MTPDchatlists_chatlistInvite &data) {
|
result.match([&](const MTPDchatlists_chatlistInvite &data) {
|
||||||
title = ParseTextWithEntities(session, data.vtitle());
|
title.text = ParseTextWithEntities(session, data.vtitle());
|
||||||
|
title.isStatic = data.is_title_noanimate();
|
||||||
iconEmoji = data.vemoticon().value_or_empty();
|
iconEmoji = data.vemoticon().value_or_empty();
|
||||||
peers = parseList(data.vpeers());
|
peers = parseList(data.vpeers());
|
||||||
}, [&](const MTPDchatlists_chatlistInviteAlready &data) {
|
}, [&](const MTPDchatlists_chatlistInviteAlready &data) {
|
||||||
|
@ -832,7 +837,7 @@ void ProcessFilterUpdate(
|
||||||
|
|
||||||
void ProcessFilterRemove(
|
void ProcessFilterRemove(
|
||||||
base::weak_ptr<Window::SessionController> weak,
|
base::weak_ptr<Window::SessionController> weak,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
QString iconEmoji,
|
QString iconEmoji,
|
||||||
std::vector<not_null<PeerData*>> all,
|
std::vector<not_null<PeerData*>> all,
|
||||||
std::vector<not_null<PeerData*>> suggest,
|
std::vector<not_null<PeerData*>> suggest,
|
||||||
|
@ -867,16 +872,18 @@ void ProcessFilterRemove(
|
||||||
raw->adjust(min, max, addedTop);
|
raw->adjust(min, max, addedTop);
|
||||||
}, type, title, iconEmoji, rpl::single(0), horizontalFilters);
|
}, type, title, iconEmoji, rpl::single(0), horizontalFilters);
|
||||||
|
|
||||||
|
const auto isStatic = title.isStatic;
|
||||||
const auto makeContext = [=](Fn<void()> update) {
|
const auto makeContext = [=](Fn<void()> update) {
|
||||||
return Core::MarkedTextContext{
|
return Core::MarkedTextContext{
|
||||||
.session = &strong->session(),
|
.session = &strong->session(),
|
||||||
.customEmojiRepaint = update,
|
.customEmojiRepaint = update,
|
||||||
|
.customEmojiLoopLimit = isStatic ? -1 : 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
auto owned = Ui::FilterLinkProcessButton(
|
auto owned = Ui::FilterLinkProcessButton(
|
||||||
box,
|
box,
|
||||||
type,
|
type,
|
||||||
title,
|
title.text,
|
||||||
makeContext,
|
makeContext,
|
||||||
std::move(badge));
|
std::move(badge));
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ class SessionController;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class ChatFilter;
|
class ChatFilter;
|
||||||
|
struct ChatFilterTitle;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Api {
|
namespace Api {
|
||||||
|
@ -36,7 +37,7 @@ void ProcessFilterUpdate(
|
||||||
|
|
||||||
void ProcessFilterRemove(
|
void ProcessFilterRemove(
|
||||||
base::weak_ptr<Window::SessionController> weak,
|
base::weak_ptr<Window::SessionController> weak,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
QString iconEmoji,
|
QString iconEmoji,
|
||||||
std::vector<not_null<PeerData*>> all,
|
std::vector<not_null<PeerData*>> all,
|
||||||
std::vector<not_null<PeerData*>> suggest,
|
std::vector<not_null<PeerData*>> suggest,
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/filters/edit_filter_box.h"
|
#include "boxes/filters/edit_filter_box.h"
|
||||||
#include "boxes/premium_limits_box.h"
|
#include "boxes/premium_limits_box.h"
|
||||||
#include "core/application.h" // primaryWindow
|
#include "core/application.h" // primaryWindow
|
||||||
|
#include "core/ui_integration.h"
|
||||||
#include "data/data_chat_filters.h"
|
#include "data/data_chat_filters.h"
|
||||||
#include "data/data_premium_limits.h"
|
#include "data/data_premium_limits.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
@ -22,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "ui/rect.h"
|
#include "ui/rect.h"
|
||||||
#include "ui/text/text_utilities.h" // Ui::Text::Bold
|
#include "ui/text/text_utilities.h" // Ui::Text::Bold
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/menu/menu_action.h"
|
#include "ui/widgets/menu/menu_action.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
|
@ -169,15 +171,26 @@ void ChangeFilterById(
|
||||||
)).done([=, chat = history->peer->name(), name = filter.title()] {
|
)).done([=, chat = history->peer->name(), name = filter.title()] {
|
||||||
const auto account = not_null(&history->session().account());
|
const auto account = not_null(&history->session().account());
|
||||||
if (const auto controller = Core::App().windowFor(account)) {
|
if (const auto controller = Core::App().windowFor(account)) {
|
||||||
controller->showToast((add
|
const auto isStatic = name.isStatic;
|
||||||
? tr::lng_filters_toast_add
|
const auto textContext = [=](not_null<QWidget*> widget) {
|
||||||
: tr::lng_filters_toast_remove)(
|
return Core::MarkedTextContext{
|
||||||
tr::now,
|
.session = &history->session(),
|
||||||
lt_chat,
|
.customEmojiRepaint = [=] { widget->update(); },
|
||||||
Ui::Text::Bold(chat),
|
.customEmojiLoopLimit = isStatic ? -1 : 0,
|
||||||
lt_folder,
|
};
|
||||||
Ui::Text::Wrapped(name, EntityType::Bold),
|
};
|
||||||
Ui::Text::WithEntities));
|
controller->showToast({
|
||||||
|
.text = (add
|
||||||
|
? tr::lng_filters_toast_add
|
||||||
|
: tr::lng_filters_toast_remove)(
|
||||||
|
tr::now,
|
||||||
|
lt_chat,
|
||||||
|
Ui::Text::Bold(chat),
|
||||||
|
lt_folder,
|
||||||
|
Ui::Text::Wrapped(name.text, EntityType::Bold),
|
||||||
|
Ui::Text::WithEntities),
|
||||||
|
.textContext = textContext,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
LOG(("API Error: failed to %1 a dialog to a folder. %2")
|
LOG(("API Error: failed to %1 a dialog to a folder. %2")
|
||||||
|
@ -279,7 +292,7 @@ void FillChooseFilterMenu(
|
||||||
menu->st().menu,
|
menu->st().menu,
|
||||||
Ui::Menu::CreateAction(
|
Ui::Menu::CreateAction(
|
||||||
menu.get(), // todo filter emoji
|
menu.get(), // todo filter emoji
|
||||||
Ui::Text::FixAmpersandInAction(filter.title().text),
|
Ui::Text::FixAmpersandInAction(filter.title().text.text),
|
||||||
std::move(callback)),
|
std::move(callback)),
|
||||||
contains ? &st::mediaPlayerMenuCheck : nullptr,
|
contains ? &st::mediaPlayerMenuCheck : nullptr,
|
||||||
contains ? &st::mediaPlayerMenuCheck : nullptr);
|
contains ? &st::mediaPlayerMenuCheck : nullptr);
|
||||||
|
|
|
@ -40,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/filter_icons.h"
|
#include "ui/filter_icons.h"
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
|
#include "ui/power_saving.h"
|
||||||
#include "ui/vertical_list.h"
|
#include "ui/vertical_list.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/fields/input_field.h"
|
#include "ui/widgets/fields/input_field.h"
|
||||||
|
@ -352,6 +353,8 @@ void EditFilterBox(
|
||||||
rpl::variable<bool> hasLinks;
|
rpl::variable<bool> hasLinks;
|
||||||
rpl::variable<bool> chatlist;
|
rpl::variable<bool> chatlist;
|
||||||
rpl::variable<bool> creating;
|
rpl::variable<bool> creating;
|
||||||
|
rpl::variable<TextWithEntities> title;
|
||||||
|
rpl::variable<bool> staticTitle;
|
||||||
rpl::variable<int> colorIndex;
|
rpl::variable<int> colorIndex;
|
||||||
};
|
};
|
||||||
const auto owner = &window->session().data();
|
const auto owner = &window->session().data();
|
||||||
|
@ -359,6 +362,8 @@ void EditFilterBox(
|
||||||
.rules = filter,
|
.rules = filter,
|
||||||
.chatlist = filter.chatlist(),
|
.chatlist = filter.chatlist(),
|
||||||
.creating = filter.title().empty(),
|
.creating = filter.title().empty(),
|
||||||
|
.title = filter.titleText(),
|
||||||
|
.staticTitle = filter.staticTitle(),
|
||||||
});
|
});
|
||||||
state->colorIndex = filter.colorIndex().value_or(kNoTag);
|
state->colorIndex = filter.colorIndex().value_or(kNoTag);
|
||||||
state->links = owner->chatsFilters().chatlistLinks(filter.id()),
|
state->links = owner->chatsFilters().chatlistLinks(filter.id()),
|
||||||
|
@ -404,7 +409,7 @@ void EditFilterBox(
|
||||||
}, box->lifetime());
|
}, box->lifetime());
|
||||||
|
|
||||||
const auto content = box->verticalLayout();
|
const auto content = box->verticalLayout();
|
||||||
const auto current = filter.title();
|
const auto current = state->title.current();
|
||||||
const auto name = content->add(
|
const auto name = content->add(
|
||||||
object_ptr<Ui::InputField>(
|
object_ptr<Ui::InputField>(
|
||||||
box,
|
box,
|
||||||
|
@ -422,6 +427,44 @@ void EditFilterBox(
|
||||||
const auto nameEditing = box->lifetime().make_state<NameEditing>(
|
const auto nameEditing = box->lifetime().make_state<NameEditing>(
|
||||||
NameEditing{ name });
|
NameEditing{ name });
|
||||||
|
|
||||||
|
const auto staticTitle = Ui::CreateChild<Ui::LinkButton>(
|
||||||
|
name,
|
||||||
|
QString());
|
||||||
|
staticTitle->setClickedCallback([=] {
|
||||||
|
state->staticTitle = !state->staticTitle.current();
|
||||||
|
});
|
||||||
|
state->staticTitle.value() | rpl::start_with_next([=](bool value) {
|
||||||
|
staticTitle->setText(value
|
||||||
|
? tr::lng_filters_enable_animations(tr::now)
|
||||||
|
: tr::lng_filters_disable_animations(tr::now));
|
||||||
|
const auto paused = [=] {
|
||||||
|
using namespace Window;
|
||||||
|
return window->isGifPausedAtLeastFor(GifPauseReason::Layer);
|
||||||
|
};
|
||||||
|
name->setCustomTextContext([=](Fn<void()> repaint) {
|
||||||
|
return std::any(Core::MarkedTextContext{
|
||||||
|
.session = session,
|
||||||
|
.customEmojiRepaint = std::move(repaint),
|
||||||
|
.customEmojiLoopLimit = value ? -1 : 0,
|
||||||
|
});
|
||||||
|
}, [paused] {
|
||||||
|
return On(PowerSaving::kEmojiChat) || paused();
|
||||||
|
}, [paused] {
|
||||||
|
return On(PowerSaving::kChatSpoiler) || paused();
|
||||||
|
});
|
||||||
|
name->update();
|
||||||
|
}, staticTitle->lifetime());
|
||||||
|
|
||||||
|
rpl::combine(
|
||||||
|
staticTitle->widthValue(),
|
||||||
|
name->widthValue()
|
||||||
|
) | rpl::start_with_next([=](int inner, int outer) {
|
||||||
|
staticTitle->moveToRight(
|
||||||
|
st::windowFilterStaticTitlePosition.x(),
|
||||||
|
st::windowFilterStaticTitlePosition.y(),
|
||||||
|
outer);
|
||||||
|
}, staticTitle->lifetime());
|
||||||
|
|
||||||
state->creating.value(
|
state->creating.value(
|
||||||
) | rpl::filter(!_1) | rpl::start_with_next([=] {
|
) | rpl::filter(!_1) | rpl::start_with_next([=] {
|
||||||
nameEditing->custom = true;
|
nameEditing->custom = true;
|
||||||
|
@ -432,7 +475,13 @@ void EditFilterBox(
|
||||||
if (!nameEditing->settingDefault) {
|
if (!nameEditing->settingDefault) {
|
||||||
nameEditing->custom = true;
|
nameEditing->custom = true;
|
||||||
}
|
}
|
||||||
|
auto entered = name->getTextWithTags();
|
||||||
|
state->title = TextWithEntities{
|
||||||
|
std::move(entered.text),
|
||||||
|
TextUtilities::ConvertTextTagsToEntities(entered.tags),
|
||||||
|
};
|
||||||
}, name->lifetime());
|
}, name->lifetime());
|
||||||
|
|
||||||
const auto updateDefaultTitle = [=](const Data::ChatFilter &filter) {
|
const auto updateDefaultTitle = [=](const Data::ChatFilter &filter) {
|
||||||
if (nameEditing->custom) {
|
if (nameEditing->custom) {
|
||||||
return;
|
return;
|
||||||
|
@ -444,13 +493,11 @@ void EditFilterBox(
|
||||||
nameEditing->settingDefault = false;
|
nameEditing->settingDefault = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto nameWithEntities = [=](bool upper = false) {
|
|
||||||
const auto entered = name->getTextWithTags();
|
state->title.value(
|
||||||
return TextWithEntities{
|
) | rpl::start_with_next([=](const TextWithEntities &value) {
|
||||||
(upper ? entered.text.toUpper() : entered.text),
|
staticTitle->setVisible(!value.entities.isEmpty());
|
||||||
TextUtilities::ConvertTextTagsToEntities(entered.tags),
|
}, staticTitle->lifetime());
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto outer = box->getDelegate()->outerContainer();
|
const auto outer = box->getDelegate()->outerContainer();
|
||||||
CreateIconSelector(
|
CreateIconSelector(
|
||||||
|
@ -595,10 +642,16 @@ void EditFilterBox(
|
||||||
const auto palette = [](int i) {
|
const auto palette = [](int i) {
|
||||||
return Ui::EmptyUserpic::UserpicColor(i).color2;
|
return Ui::EmptyUserpic::UserpicColor(i).color2;
|
||||||
};
|
};
|
||||||
name->changes() | rpl::start_with_next([=] {
|
const auto upperTitle = [=] {
|
||||||
|
auto value = state->title.current();
|
||||||
|
value.text = value.text.toUpper();
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
state->title.changes(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
tag->context.color = palette(state->colorIndex.current())->c;
|
tag->context.color = palette(state->colorIndex.current())->c;
|
||||||
tag->frame = Ui::ChatsFilterTag(
|
tag->frame = Ui::ChatsFilterTag(
|
||||||
nameWithEntities(true),
|
upperTitle(),
|
||||||
tag->context);
|
tag->context);
|
||||||
preview->update();
|
preview->update();
|
||||||
}, preview->lifetime());
|
}, preview->lifetime());
|
||||||
|
@ -615,7 +668,7 @@ void EditFilterBox(
|
||||||
if (progress == 1) {
|
if (progress == 1) {
|
||||||
tag->context.color = color->c;
|
tag->context.color = color->c;
|
||||||
tag->frame = Ui::ChatsFilterTag(
|
tag->frame = Ui::ChatsFilterTag(
|
||||||
nameWithEntities(true),
|
upperTitle(),
|
||||||
tag->context);
|
tag->context);
|
||||||
if (i == kNoTag) {
|
if (i == kNoTag) {
|
||||||
tag->alpha = 0.;
|
tag->alpha = 0.;
|
||||||
|
@ -641,7 +694,7 @@ void EditFilterBox(
|
||||||
buttons[now]->setSelectedProgress(progress);
|
buttons[now]->setSelectedProgress(progress);
|
||||||
tag->context.color = anim::color(c1, c2, progress);
|
tag->context.color = anim::color(c1, c2, progress);
|
||||||
tag->frame = Ui::ChatsFilterTag(
|
tag->frame = Ui::ChatsFilterTag(
|
||||||
nameWithEntities(true),
|
upperTitle(),
|
||||||
tag->context);
|
tag->context);
|
||||||
tag->alpha = anim::interpolateF(a1, a2, progress);
|
tag->alpha = anim::interpolateF(a1, a2, progress);
|
||||||
preview->update();
|
preview->update();
|
||||||
|
@ -689,7 +742,9 @@ void EditFilterBox(
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto collect = [=]() -> std::optional<Data::ChatFilter> {
|
const auto collect = [=]() -> std::optional<Data::ChatFilter> {
|
||||||
const auto title = nameWithEntities();
|
auto title = state->title.current();
|
||||||
|
const auto staticTitle = !title.entities.isEmpty()
|
||||||
|
&& state->staticTitle.current();
|
||||||
const auto rules = data->current();
|
const auto rules = data->current();
|
||||||
if (title.empty()) {
|
if (title.empty()) {
|
||||||
name->showError();
|
name->showError();
|
||||||
|
@ -708,7 +763,9 @@ void EditFilterBox(
|
||||||
const auto colorIndex = (rawColorIndex >= kNoTag
|
const auto colorIndex = (rawColorIndex >= kNoTag
|
||||||
? std::nullopt
|
? std::nullopt
|
||||||
: std::make_optional(rawColorIndex));
|
: std::make_optional(rawColorIndex));
|
||||||
return rules.withTitle(title).withColorIndex(colorIndex);
|
return rules.withTitle(
|
||||||
|
{ std::move(title), staticTitle }
|
||||||
|
).withColorIndex(colorIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
Ui::AddSubsectionTitle(
|
Ui::AddSubsectionTitle(
|
||||||
|
|
|
@ -151,7 +151,10 @@ ExceptionRow::ExceptionRow(
|
||||||
if (!filters.empty()) {
|
if (!filters.empty()) {
|
||||||
filters.append(u", "_q);
|
filters.append(u", "_q);
|
||||||
}
|
}
|
||||||
filters.append(filter.title());
|
auto title = filter.title();
|
||||||
|
filters.append(title.isStatic
|
||||||
|
? Data::ForceCustomEmojiStatic(std::move(title.text))
|
||||||
|
: std::move(title.text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!filters.empty()) {
|
if (!filters.empty()) {
|
||||||
|
|
|
@ -483,7 +483,7 @@ private:
|
||||||
const not_null<Window::SessionController*> _window;
|
const not_null<Window::SessionController*> _window;
|
||||||
InviteLinkData _data;
|
InviteLinkData _data;
|
||||||
|
|
||||||
TextWithEntities _filterTitle;
|
Data::ChatFilterTitle _filterTitle;
|
||||||
base::flat_set<not_null<History*>> _filterChats;
|
base::flat_set<not_null<History*>> _filterChats;
|
||||||
base::flat_map<not_null<PeerData*>, QString> _denied;
|
base::flat_map<not_null<PeerData*>, QString> _denied;
|
||||||
rpl::variable<base::flat_set<not_null<PeerData*>>> _selected;
|
rpl::variable<base::flat_set<not_null<PeerData*>>> _selected;
|
||||||
|
@ -536,10 +536,12 @@ void LinkController::addHeader(not_null<Ui::VerticalLayout*> container) {
|
||||||
}, verticalLayout->lifetime());
|
}, verticalLayout->lifetime());
|
||||||
verticalLayout->add(std::move(icon.widget));
|
verticalLayout->add(std::move(icon.widget));
|
||||||
|
|
||||||
|
const auto isStatic = _filterTitle.isStatic;
|
||||||
const auto makeContext = [=](Fn<void()> update) {
|
const auto makeContext = [=](Fn<void()> update) {
|
||||||
return Core::MarkedTextContext{
|
return Core::MarkedTextContext{
|
||||||
.session = &_window->session(),
|
.session = &_window->session(),
|
||||||
.customEmojiRepaint = update,
|
.customEmojiRepaint = update,
|
||||||
|
.customEmojiLoopLimit = isStatic ? -1 : 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
verticalLayout->add(
|
verticalLayout->add(
|
||||||
|
@ -552,7 +554,7 @@ void LinkController::addHeader(not_null<Ui::VerticalLayout*> container) {
|
||||||
: tr::lng_filters_link_share_about(
|
: tr::lng_filters_link_share_about(
|
||||||
lt_folder,
|
lt_folder,
|
||||||
rpl::single(Ui::Text::Wrapped(
|
rpl::single(Ui::Text::Wrapped(
|
||||||
_filterTitle,
|
_filterTitle.text,
|
||||||
EntityType::Bold)),
|
EntityType::Bold)),
|
||||||
Ui::Text::WithEntities)),
|
Ui::Text::WithEntities)),
|
||||||
st::settingsFilterDividerLabel,
|
st::settingsFilterDividerLabel,
|
||||||
|
|
|
@ -286,6 +286,9 @@ std::unique_ptr<Ui::Text::CustomEmoji> UiIntegration::createCustomEmoji(
|
||||||
return std::make_unique<Ui::Text::LimitedLoopsEmoji>(
|
return std::make_unique<Ui::Text::LimitedLoopsEmoji>(
|
||||||
std::move(result),
|
std::move(result),
|
||||||
my->customEmojiLoopLimit);
|
my->customEmojiLoopLimit);
|
||||||
|
} else if (my->customEmojiLoopLimit) {
|
||||||
|
return std::make_unique<Ui::Text::FirstFrameEmoji>(
|
||||||
|
std::move(result));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,22 @@ constexpr auto kLoadExceptionsPerRequest = 100;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TextWithEntities ForceCustomEmojiStatic(TextWithEntities text) {
|
||||||
|
for (auto &entity : text.entities) {
|
||||||
|
if (entity.type() == EntityType::CustomEmoji) {
|
||||||
|
entity = EntityInText(
|
||||||
|
EntityType::CustomEmoji,
|
||||||
|
entity.offset(),
|
||||||
|
entity.length(),
|
||||||
|
u"force-static:"_q + entity.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
ChatFilter::ChatFilter(
|
ChatFilter::ChatFilter(
|
||||||
FilterId id,
|
FilterId id,
|
||||||
TextWithEntities title,
|
ChatFilterTitle title,
|
||||||
QString iconEmoji,
|
QString iconEmoji,
|
||||||
std::optional<uint8> colorIndex,
|
std::optional<uint8> colorIndex,
|
||||||
Flags flags,
|
Flags flags,
|
||||||
|
@ -50,13 +63,15 @@ ChatFilter::ChatFilter(
|
||||||
std::vector<not_null<History*>> pinned,
|
std::vector<not_null<History*>> pinned,
|
||||||
base::flat_set<not_null<History*>> never)
|
base::flat_set<not_null<History*>> never)
|
||||||
: _id(id)
|
: _id(id)
|
||||||
, _title(std::move(title))
|
, _title(std::move(title.text))
|
||||||
, _iconEmoji(std::move(iconEmoji))
|
, _iconEmoji(std::move(iconEmoji))
|
||||||
, _colorIndex(colorIndex)
|
, _colorIndex(colorIndex)
|
||||||
, _always(std::move(always))
|
, _always(std::move(always))
|
||||||
, _pinned(std::move(pinned))
|
, _pinned(std::move(pinned))
|
||||||
, _never(std::move(never))
|
, _never(std::move(never))
|
||||||
, _flags(flags) {
|
, _flags(title.isStatic
|
||||||
|
? (flags | Flag::StaticTitle)
|
||||||
|
: (flags & ~Flag::StaticTitle)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatFilter ChatFilter::FromTL(
|
ChatFilter ChatFilter::FromTL(
|
||||||
|
@ -70,7 +85,8 @@ ChatFilter ChatFilter::FromTL(
|
||||||
| (data.is_bots() ? Flag::Bots : Flag(0))
|
| (data.is_bots() ? Flag::Bots : Flag(0))
|
||||||
| (data.is_exclude_muted() ? Flag::NoMuted : Flag(0))
|
| (data.is_exclude_muted() ? Flag::NoMuted : Flag(0))
|
||||||
| (data.is_exclude_read() ? Flag::NoRead : Flag(0))
|
| (data.is_exclude_read() ? Flag::NoRead : Flag(0))
|
||||||
| (data.is_exclude_archived() ? Flag::NoArchived : Flag(0));
|
| (data.is_exclude_archived() ? Flag::NoArchived : Flag(0))
|
||||||
|
| (data.is_title_noanimate() ? Flag::StaticTitle : Flag(0));
|
||||||
auto &&to_histories = ranges::views::transform([&](
|
auto &&to_histories = ranges::views::transform([&](
|
||||||
const MTPInputPeer &input) {
|
const MTPInputPeer &input) {
|
||||||
const auto peer = Data::PeerFromInputMTP(owner, input);
|
const auto peer = Data::PeerFromInputMTP(owner, input);
|
||||||
|
@ -96,7 +112,10 @@ ChatFilter ChatFilter::FromTL(
|
||||||
};
|
};
|
||||||
return ChatFilter(
|
return ChatFilter(
|
||||||
data.vid().v,
|
data.vid().v,
|
||||||
Api::ParseTextWithEntities(&owner->session(), data.vtitle()),
|
{
|
||||||
|
Api::ParseTextWithEntities(&owner->session(), data.vtitle()),
|
||||||
|
data.is_title_noanimate(),
|
||||||
|
},
|
||||||
qs(data.vemoticon().value_or_empty()),
|
qs(data.vemoticon().value_or_empty()),
|
||||||
data.vcolor()
|
data.vcolor()
|
||||||
? std::make_optional(data.vcolor()->v)
|
? std::make_optional(data.vcolor()->v)
|
||||||
|
@ -105,7 +124,7 @@ ChatFilter ChatFilter::FromTL(
|
||||||
std::move(list),
|
std::move(list),
|
||||||
std::move(pinned),
|
std::move(pinned),
|
||||||
{ never.begin(), never.end() });
|
{ never.begin(), never.end() });
|
||||||
}, [](const MTPDdialogFilterDefault &d) {
|
}, [](const MTPDdialogFilterDefault &) {
|
||||||
return ChatFilter();
|
return ChatFilter();
|
||||||
}, [&](const MTPDdialogFilterChatlist &data) {
|
}, [&](const MTPDdialogFilterChatlist &data) {
|
||||||
auto &&to_histories = ranges::views::transform([&](
|
auto &&to_histories = ranges::views::transform([&](
|
||||||
|
@ -144,13 +163,17 @@ ChatFilter ChatFilter::FromTL(
|
||||||
};
|
};
|
||||||
return ChatFilter(
|
return ChatFilter(
|
||||||
data.vid().v,
|
data.vid().v,
|
||||||
Api::ParseTextWithEntities(&owner->session(), data.vtitle()),
|
{
|
||||||
|
Api::ParseTextWithEntities(&owner->session(), data.vtitle()),
|
||||||
|
data.is_title_noanimate(),
|
||||||
|
},
|
||||||
qs(data.vemoticon().value_or_empty()),
|
qs(data.vemoticon().value_or_empty()),
|
||||||
data.vcolor()
|
data.vcolor()
|
||||||
? std::make_optional(data.vcolor()->v)
|
? std::make_optional(data.vcolor()->v)
|
||||||
: std::nullopt,
|
: std::nullopt,
|
||||||
(Flag::Chatlist
|
(Flag::Chatlist
|
||||||
| (data.is_has_my_invites() ? Flag::HasMyLinks : Flag())),
|
| (data.is_has_my_invites() ? Flag::HasMyLinks : Flag())
|
||||||
|
| (data.is_title_noanimate() ? Flag::StaticTitle : Flag(0))),
|
||||||
std::move(list),
|
std::move(list),
|
||||||
std::move(pinned),
|
std::move(pinned),
|
||||||
{});
|
{});
|
||||||
|
@ -163,9 +186,14 @@ ChatFilter ChatFilter::withId(FilterId id) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatFilter ChatFilter::withTitle(TextWithEntities title) const {
|
ChatFilter ChatFilter::withTitle(ChatFilterTitle title) const {
|
||||||
auto result = *this;
|
auto result = *this;
|
||||||
result._title = std::move(title);
|
result._title = std::move(title.text);
|
||||||
|
if (title.isStatic) {
|
||||||
|
result._flags |= Flag::StaticTitle;
|
||||||
|
} else {
|
||||||
|
result._flags &= ~Flag::StaticTitle;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +247,8 @@ MTPDialogFilter ChatFilter::tl(FilterId replaceId) const {
|
||||||
if (_flags & Flag::Chatlist) {
|
if (_flags & Flag::Chatlist) {
|
||||||
using TLFlag = MTPDdialogFilterChatlist::Flag;
|
using TLFlag = MTPDdialogFilterChatlist::Flag;
|
||||||
const auto flags = TLFlag::f_emoticon
|
const auto flags = TLFlag::f_emoticon
|
||||||
| (_colorIndex ? TLFlag::f_color : TLFlag(0));
|
| (_colorIndex ? TLFlag::f_color : TLFlag(0))
|
||||||
|
| (staticTitle() ? TLFlag::f_title_noanimate : TLFlag(0));
|
||||||
return MTP_dialogFilterChatlist(
|
return MTP_dialogFilterChatlist(
|
||||||
MTP_flags(flags),
|
MTP_flags(flags),
|
||||||
MTP_int(replaceId ? replaceId : _id),
|
MTP_int(replaceId ? replaceId : _id),
|
||||||
|
@ -232,6 +261,7 @@ MTPDialogFilter ChatFilter::tl(FilterId replaceId) const {
|
||||||
using TLFlag = MTPDdialogFilter::Flag;
|
using TLFlag = MTPDdialogFilter::Flag;
|
||||||
const auto flags = TLFlag::f_emoticon
|
const auto flags = TLFlag::f_emoticon
|
||||||
| (_colorIndex ? TLFlag::f_color : TLFlag(0))
|
| (_colorIndex ? TLFlag::f_color : TLFlag(0))
|
||||||
|
| (staticTitle() ? TLFlag::f_title_noanimate : TLFlag(0))
|
||||||
| ((_flags & Flag::Contacts) ? TLFlag::f_contacts : TLFlag(0))
|
| ((_flags & Flag::Contacts) ? TLFlag::f_contacts : TLFlag(0))
|
||||||
| ((_flags & Flag::NonContacts) ? TLFlag::f_non_contacts : TLFlag(0))
|
| ((_flags & Flag::NonContacts) ? TLFlag::f_non_contacts : TLFlag(0))
|
||||||
| ((_flags & Flag::Groups) ? TLFlag::f_groups : TLFlag(0))
|
| ((_flags & Flag::Groups) ? TLFlag::f_groups : TLFlag(0))
|
||||||
|
@ -262,10 +292,14 @@ FilterId ChatFilter::id() const {
|
||||||
return _id;
|
return _id;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextWithEntities ChatFilter::title() const {
|
const TextWithEntities &ChatFilter::titleText() const {
|
||||||
return _title;
|
return _title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatFilterTitle ChatFilter::title() const {
|
||||||
|
return { _title, !!(_flags & Flag::StaticTitle) };
|
||||||
|
}
|
||||||
|
|
||||||
QString ChatFilter::iconEmoji() const {
|
QString ChatFilter::iconEmoji() const {
|
||||||
return _iconEmoji;
|
return _iconEmoji;
|
||||||
}
|
}
|
||||||
|
@ -278,6 +312,10 @@ ChatFilter::Flags ChatFilter::flags() const {
|
||||||
return _flags;
|
return _flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChatFilter::staticTitle() const {
|
||||||
|
return _flags & Flag::StaticTitle;
|
||||||
|
}
|
||||||
|
|
||||||
bool ChatFilter::chatlist() const {
|
bool ChatFilter::chatlist() const {
|
||||||
return _flags & Flag::Chatlist;
|
return _flags & Flag::Chatlist;
|
||||||
}
|
}
|
||||||
|
@ -669,7 +707,8 @@ bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) {
|
||||||
|| (filter.hasMyLinks() != updated.hasMyLinks());
|
|| (filter.hasMyLinks() != updated.hasMyLinks());
|
||||||
const auto listUpdated = rulesChanged
|
const auto listUpdated = rulesChanged
|
||||||
|| pinnedChanged
|
|| pinnedChanged
|
||||||
|| (filter.title() != updated.title())
|
|| (filter.titleText() != updated.titleText())
|
||||||
|
|| (filter.staticTitle() != updated.staticTitle())
|
||||||
|| (filter.iconEmoji() != updated.iconEmoji());
|
|| (filter.iconEmoji() != updated.iconEmoji());
|
||||||
const auto colorChanged = filter.colorIndex() != updated.colorIndex();
|
const auto colorChanged = filter.colorIndex() != updated.colorIndex();
|
||||||
const auto colorExistenceChanged = (!filter.colorIndex())
|
const auto colorExistenceChanged = (!filter.colorIndex())
|
||||||
|
|
|
@ -25,6 +25,17 @@ namespace Data {
|
||||||
|
|
||||||
class Session;
|
class Session;
|
||||||
|
|
||||||
|
struct ChatFilterTitle {
|
||||||
|
TextWithEntities text;
|
||||||
|
bool isStatic = false;
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const {
|
||||||
|
return text.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] TextWithEntities ForceCustomEmojiStatic(TextWithEntities text);
|
||||||
|
|
||||||
class ChatFilter final {
|
class ChatFilter final {
|
||||||
public:
|
public:
|
||||||
enum class Flag : ushort {
|
enum class Flag : ushort {
|
||||||
|
@ -40,9 +51,10 @@ public:
|
||||||
|
|
||||||
Chatlist = (1 << 8),
|
Chatlist = (1 << 8),
|
||||||
HasMyLinks = (1 << 9),
|
HasMyLinks = (1 << 9),
|
||||||
|
StaticTitle = (1 << 10),
|
||||||
|
|
||||||
NewChats = (1 << 10), // Telegram Business exceptions.
|
NewChats = (1 << 11), // Telegram Business exceptions.
|
||||||
ExistingChats = (1 << 11),
|
ExistingChats = (1 << 12),
|
||||||
};
|
};
|
||||||
friend constexpr inline bool is_flag_type(Flag) { return true; };
|
friend constexpr inline bool is_flag_type(Flag) { return true; };
|
||||||
using Flags = base::flags<Flag>;
|
using Flags = base::flags<Flag>;
|
||||||
|
@ -50,7 +62,7 @@ public:
|
||||||
ChatFilter() = default;
|
ChatFilter() = default;
|
||||||
ChatFilter(
|
ChatFilter(
|
||||||
FilterId id,
|
FilterId id,
|
||||||
TextWithEntities title,
|
ChatFilterTitle title,
|
||||||
QString iconEmoji,
|
QString iconEmoji,
|
||||||
std::optional<uint8> colorIndex,
|
std::optional<uint8> colorIndex,
|
||||||
Flags flags,
|
Flags flags,
|
||||||
|
@ -59,7 +71,7 @@ public:
|
||||||
base::flat_set<not_null<History*>> never);
|
base::flat_set<not_null<History*>> never);
|
||||||
|
|
||||||
[[nodiscard]] ChatFilter withId(FilterId id) const;
|
[[nodiscard]] ChatFilter withId(FilterId id) const;
|
||||||
[[nodiscard]] ChatFilter withTitle(TextWithEntities title) const;
|
[[nodiscard]] ChatFilter withTitle(ChatFilterTitle title) const;
|
||||||
[[nodiscard]] ChatFilter withColorIndex(std::optional<uint8>) const;
|
[[nodiscard]] ChatFilter withColorIndex(std::optional<uint8>) const;
|
||||||
[[nodiscard]] ChatFilter withChatlist(
|
[[nodiscard]] ChatFilter withChatlist(
|
||||||
bool chatlist,
|
bool chatlist,
|
||||||
|
@ -72,10 +84,12 @@ public:
|
||||||
[[nodiscard]] MTPDialogFilter tl(FilterId replaceId = 0) const;
|
[[nodiscard]] MTPDialogFilter tl(FilterId replaceId = 0) const;
|
||||||
|
|
||||||
[[nodiscard]] FilterId id() const;
|
[[nodiscard]] FilterId id() const;
|
||||||
[[nodiscard]] TextWithEntities title() const;
|
[[nodiscard]] ChatFilterTitle title() const;
|
||||||
|
[[nodiscard]] const TextWithEntities &titleText() const;
|
||||||
[[nodiscard]] QString iconEmoji() const;
|
[[nodiscard]] QString iconEmoji() const;
|
||||||
[[nodiscard]] std::optional<uint8> colorIndex() const;
|
[[nodiscard]] std::optional<uint8> colorIndex() const;
|
||||||
[[nodiscard]] Flags flags() const;
|
[[nodiscard]] Flags flags() const;
|
||||||
|
[[nodiscard]] bool staticTitle() const;
|
||||||
[[nodiscard]] bool chatlist() const;
|
[[nodiscard]] bool chatlist() const;
|
||||||
[[nodiscard]] bool hasMyLinks() const;
|
[[nodiscard]] bool hasMyLinks() const;
|
||||||
[[nodiscard]] const base::flat_set<not_null<History*>> &always() const;
|
[[nodiscard]] const base::flat_set<not_null<History*>> &always() const;
|
||||||
|
@ -99,7 +113,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const ChatFilter &a, const ChatFilter &b) {
|
inline bool operator==(const ChatFilter &a, const ChatFilter &b) {
|
||||||
return (a.title() == b.title())
|
return (a.titleText() == b.titleText())
|
||||||
&& (a.iconEmoji() == b.iconEmoji())
|
&& (a.iconEmoji() == b.iconEmoji())
|
||||||
&& (a.colorIndex() == b.colorIndex())
|
&& (a.colorIndex() == b.colorIndex())
|
||||||
&& (a.flags() == b.flags())
|
&& (a.flags() == b.flags())
|
||||||
|
|
|
@ -113,6 +113,10 @@ private:
|
||||||
return u"scaled-custom:"_q;
|
return u"scaled-custom:"_q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QString ForceStaticPrefix() {
|
||||||
|
return u"force-static:"_q;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] QString InternalPadding(QMargins value) {
|
[[nodiscard]] QString InternalPadding(QMargins value) {
|
||||||
return value.isNull() ? QString() : QString(",%1,%2,%3,%4"
|
return value.isNull() ? QString() : QString(",%1,%2,%3,%4"
|
||||||
).arg(value.left()
|
).arg(value.left()
|
||||||
|
@ -554,6 +558,10 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
|
||||||
const auto original = data.mid(ScaledCustomPrefix().size());
|
const auto original = data.mid(ScaledCustomPrefix().size());
|
||||||
return Ui::MakeScaledCustomEmoji(
|
return Ui::MakeScaledCustomEmoji(
|
||||||
create(original, std::move(update), SizeTag::Large));
|
create(original, std::move(update), SizeTag::Large));
|
||||||
|
} else if (data.startsWith(ForceStaticPrefix())) {
|
||||||
|
const auto original = data.mid(ForceStaticPrefix().size());
|
||||||
|
return std::make_unique<Ui::Text::FirstFrameEmoji>(
|
||||||
|
create(original, std::move(update), tag, sizeOverride));
|
||||||
} else if (data.startsWith(InternalPrefix())) {
|
} else if (data.startsWith(InternalPrefix())) {
|
||||||
return internal(data);
|
return internal(data);
|
||||||
} else if (data.startsWith(UserpicEmojiPrefix())) {
|
} else if (data.startsWith(UserpicEmojiPrefix())) {
|
||||||
|
|
|
@ -4181,7 +4181,7 @@ QImage *InnerWidget::cacheChatsFilterTag(
|
||||||
auto roundedText = TextWithEntities();
|
auto roundedText = TextWithEntities();
|
||||||
auto colorIndex = -1;
|
auto colorIndex = -1;
|
||||||
if (filter.id()) {
|
if (filter.id()) {
|
||||||
roundedText = filter.title();
|
roundedText = filter.title().text;
|
||||||
roundedText.text = roundedText.text.toUpper();
|
roundedText.text = roundedText.text.toUpper();
|
||||||
if (filter.colorIndex()) {
|
if (filter.colorIndex()) {
|
||||||
colorIndex = *(filter.colorIndex());
|
colorIndex = *(filter.colorIndex());
|
||||||
|
|
|
@ -194,13 +194,15 @@ void FilterRowButton::updateData(
|
||||||
bool ignoreCount) {
|
bool ignoreCount) {
|
||||||
Expects(_session != nullptr);
|
Expects(_session != nullptr);
|
||||||
|
|
||||||
|
const auto title = filter.title();
|
||||||
_title.setMarkedText(
|
_title.setMarkedText(
|
||||||
st::contactsNameStyle,
|
st::contactsNameStyle,
|
||||||
filter.title(),
|
title.text,
|
||||||
kMarkupTextOptions,
|
kMarkupTextOptions,
|
||||||
Core::MarkedTextContext{
|
Core::MarkedTextContext{
|
||||||
.session = _session,
|
.session = _session,
|
||||||
.customEmojiRepaint = [=] { update(); },
|
.customEmojiRepaint = [=] { update(); },
|
||||||
|
.customEmojiLoopLimit = title.isStatic ? -1 : 0,
|
||||||
});
|
});
|
||||||
_icon = Ui::ComputeFilterIcon(filter);
|
_icon = Ui::ComputeFilterIcon(filter);
|
||||||
_colorIndex = filter.colorIndex();
|
_colorIndex = filter.colorIndex();
|
||||||
|
|
|
@ -151,9 +151,10 @@ void ShowFiltersListMenu(
|
||||||
|
|
||||||
for (auto i = 0; i < list.size(); ++i) {
|
for (auto i = 0; i < list.size(); ++i) {
|
||||||
const auto &filter = list[i];
|
const auto &filter = list[i];
|
||||||
auto text = filter.title().empty()
|
auto title = filter.title();
|
||||||
|
auto text = title.text.empty()
|
||||||
? tr::lng_filters_all_short(tr::now)
|
? tr::lng_filters_all_short(tr::now)
|
||||||
: filter.title().text; // todo filter emoji
|
: title.text.text; // todo filter emoji
|
||||||
|
|
||||||
const auto action = state->menu->addAction(std::move(text), [=] {
|
const auto action = state->menu->addAction(std::move(text), [=] {
|
||||||
if (i != active) {
|
if (i != active) {
|
||||||
|
@ -340,9 +341,12 @@ not_null<Ui::RpWidget*> AddChatFiltersTabsStrip(
|
||||||
ranges::views::all(
|
ranges::views::all(
|
||||||
list
|
list
|
||||||
) | ranges::views::transform([](const Data::ChatFilter &filter) {
|
) | ranges::views::transform([](const Data::ChatFilter &filter) {
|
||||||
return filter.title().empty()
|
auto title = filter.title();
|
||||||
|
return title.text.empty()
|
||||||
? TextWithEntities{ tr::lng_filters_all_short(tr::now) }
|
? TextWithEntities{ tr::lng_filters_all_short(tr::now) }
|
||||||
: filter.title();
|
: title.isStatic
|
||||||
|
? Data::ForceCustomEmojiStatic(title.text)
|
||||||
|
: title.text;
|
||||||
}) | ranges::to_vector, context, paused);
|
}) | ranges::to_vector, context, paused);
|
||||||
if (!sectionsChanged) {
|
if (!sectionsChanged) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -285,8 +285,9 @@ windowFilterSmallRemoveRight: 10px;
|
||||||
windowFilterNameInput: InputField(defaultInputField) {
|
windowFilterNameInput: InputField(defaultInputField) {
|
||||||
textMargins: margins(0px, 26px, 36px, 4px);
|
textMargins: margins(0px, 26px, 36px, 4px);
|
||||||
}
|
}
|
||||||
|
windowFilterStaticTitlePosition: point(0px, 5px);
|
||||||
windowFilterIconToggleSize: size(36px, 36px);
|
windowFilterIconToggleSize: size(36px, 36px);
|
||||||
windowFilterIconTogglePosition: point(-4px, 12px);
|
windowFilterIconTogglePosition: point(-4px, 18px);
|
||||||
windwoFilterIconPanelPosition: point(-2px, -1px);
|
windwoFilterIconPanelPosition: point(-2px, -1px);
|
||||||
windowFilterIconSingle: size(44px, 42px);
|
windowFilterIconSingle: size(44px, 42px);
|
||||||
windowFilterIconPadding: margins(10px, 36px, 10px, 8px);
|
windowFilterIconPadding: margins(10px, 36px, 10px, 8px);
|
||||||
|
|
|
@ -218,7 +218,7 @@ void FiltersMenu::setupList() {
|
||||||
_setup = prepareButton(
|
_setup = prepareButton(
|
||||||
_container,
|
_container,
|
||||||
-1,
|
-1,
|
||||||
TextWithEntities{ tr::lng_filters_setup(tr::now) },
|
{ TextWithEntities{ tr::lng_filters_setup(tr::now) } },
|
||||||
Ui::FilterIcon::Edit);
|
Ui::FilterIcon::Edit);
|
||||||
_reorder = std::make_unique<Ui::VerticalLayoutReorder>(_list, &_scroll);
|
_reorder = std::make_unique<Ui::VerticalLayoutReorder>(_list, &_scroll);
|
||||||
|
|
||||||
|
@ -249,13 +249,15 @@ base::unique_qptr<Ui::SideBarButton> FiltersMenu::prepareAll() {
|
||||||
base::unique_qptr<Ui::SideBarButton> FiltersMenu::prepareButton(
|
base::unique_qptr<Ui::SideBarButton> FiltersMenu::prepareButton(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
FilterId id,
|
FilterId id,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
Ui::FilterIcon icon,
|
Ui::FilterIcon icon,
|
||||||
bool toBeginning) {
|
bool toBeginning) {
|
||||||
|
const auto isStatic = title.isStatic;
|
||||||
const auto makeContext = [=](Fn<void()> update) {
|
const auto makeContext = [=](Fn<void()> update) {
|
||||||
return Core::MarkedTextContext{
|
return Core::MarkedTextContext{
|
||||||
.session = &_session->session(),
|
.session = &_session->session(),
|
||||||
.customEmojiRepaint = std::move(update),
|
.customEmojiRepaint = std::move(update),
|
||||||
|
.customEmojiLoopLimit = isStatic ? -1 : 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const auto paused = [=] {
|
const auto paused = [=] {
|
||||||
|
@ -264,7 +266,7 @@ base::unique_qptr<Ui::SideBarButton> FiltersMenu::prepareButton(
|
||||||
};
|
};
|
||||||
auto prepared = object_ptr<Ui::SideBarButton>(
|
auto prepared = object_ptr<Ui::SideBarButton>(
|
||||||
container,
|
container,
|
||||||
id ? title : TextWithEntities{ tr::lng_filters_all(tr::now) },
|
id ? title.text : TextWithEntities{ tr::lng_filters_all(tr::now) },
|
||||||
st::windowFiltersButton,
|
st::windowFiltersButton,
|
||||||
makeContext,
|
makeContext,
|
||||||
paused);
|
paused);
|
||||||
|
|
|
@ -13,6 +13,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/side_bar_button.h"
|
#include "ui/widgets/side_bar_button.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
struct ChatFilterTitle;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class VerticalLayout;
|
class VerticalLayout;
|
||||||
class VerticalLayoutReorder;
|
class VerticalLayoutReorder;
|
||||||
|
@ -44,7 +48,7 @@ private:
|
||||||
[[nodiscard]] base::unique_qptr<Ui::SideBarButton> prepareButton(
|
[[nodiscard]] base::unique_qptr<Ui::SideBarButton> prepareButton(
|
||||||
not_null<Ui::VerticalLayout*> container,
|
not_null<Ui::VerticalLayout*> container,
|
||||||
FilterId id,
|
FilterId id,
|
||||||
TextWithEntities title,
|
Data::ChatFilterTitle title,
|
||||||
Ui::FilterIcon icon,
|
Ui::FilterIcon icon,
|
||||||
bool toBeginning = false);
|
bool toBeginning = false);
|
||||||
void setupMainMenuIcon();
|
void setupMainMenuIcon();
|
||||||
|
|
Loading…
Add table
Reference in a new issue