diff --git a/Telegram/Resources/animations/toast/chats_filter_in.tgs b/Telegram/Resources/animations/toast/chats_filter_in.tgs
new file mode 100644
index 0000000000..aba04090d0
Binary files /dev/null and b/Telegram/Resources/animations/toast/chats_filter_in.tgs differ
diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index c2175c4c81..ac4778e273 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -4580,6 +4580,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_message_tagged_with" = "Message tagged with {emoji}";
"lng_tagged_view_saved" = "View";
+"lng_add_channel_to_filter_selector" = "You can add a channel to your folder";
+"lng_add_group_to_filter_selector" = "You can add a group to your folder";
+
"lng_context_animated_emoji" = "This message contains emoji from **{name} pack**.";
"lng_context_animated_emoji_many#one" = "This message contains emoji from **{count} pack**.";
"lng_context_animated_emoji_many#other" = "This message contains emoji from **{count} packs**.";
diff --git a/Telegram/Resources/qrc/telegram/animations.qrc b/Telegram/Resources/qrc/telegram/animations.qrc
index 7c598d0da1..632d39986b 100644
--- a/Telegram/Resources/qrc/telegram/animations.qrc
+++ b/Telegram/Resources/qrc/telegram/animations.qrc
@@ -46,6 +46,7 @@
../../animations/toast/saved_messages.tgs
../../animations/toast/tagged.tgs
../../animations/my_gifts_empty.tgs
+ ../../animations/toast/chats_filter_in.tgs
../../animations/profile/profile_muting.tgs
../../animations/profile/profile_unmuting.tgs
diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style
index ba4a07b5a6..d3c2ed199c 100644
--- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style
+++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style
@@ -824,6 +824,29 @@ selfForwardsTaggerToast: Toast(defaultToast) {
padding: margins(54px, 12px, 19px, 12px);
iconPosition: point(15px, 6px);
}
+joinChatAddToFilterToast: Toast(defaultToast) {
+ minWidth: 160px;
+ maxWidth: 380px;
+ radius: 9px;
+ padding: margins(54px, 12px, 44px, 12px);
+ iconPosition: point(15px, 6px);
+}
+joinChatAddToFilterToastButton: IconButton(defaultIconButton) {
+ width: 40px;
+ height: 40px;
+
+ icon: icon{
+ { "chat/reactions_round_small", windowBgRipple },
+ { "chat/reactions_expand_panel", windowSubTextFg },
+ };
+ iconOver: icon{
+ { "chat/reactions_round_small", windowBgRipple },
+ { "chat/reactions_expand_panel", windowSubTextFg },
+ };
+ rippleAreaPosition: point(10px, 10px);
+ rippleAreaSize: 20px;
+ ripple: universalRippleAnimation;
+}
choosePeerGroupIcon: icon {{ "info/edit/create_group", lightButtonFg }};
choosePeerChannelIcon: icon {{ "info/edit/create_channel", lightButtonFg }};
diff --git a/Telegram/SourceFiles/history/view/history_view_self_forwards_tagger.cpp b/Telegram/SourceFiles/history/view/history_view_self_forwards_tagger.cpp
index 15ecec7479..82f008a0b8 100644
--- a/Telegram/SourceFiles/history/view/history_view_self_forwards_tagger.cpp
+++ b/Telegram/SourceFiles/history/view/history_view_self_forwards_tagger.cpp
@@ -10,8 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/call_delayed.h"
#include "base/event_filter.h"
#include "base/timer_rpl.h"
+#include "boxes/choose_filter_box.h"
#include "chat_helpers/share_message_phrase_factory.h"
#include "core/ui_integration.h"
+#include "data/data_chat_filters.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/stickers/data_custom_emoji.h"
@@ -27,10 +29,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast_widget.h"
#include "ui/toast/toast.h"
#include "ui/widgets/buttons.h"
+#include "ui/widgets/popup_menu.h"
#include "ui/widgets/tooltip.h"
#include "window/window_session_controller.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
+#include "styles/style_info.h"
namespace HistoryView {
namespace {
@@ -65,6 +69,20 @@ void SelfForwardsTagger::setup() {
}
showSelectorForMessages(data.ids);
}, _lifetime);
+ _controller->session().data().recentJoinChat(
+ ) | rpl::start_with_next([=](const Data::RecentJoinChat &data) {
+ if (!_controller->session().data().chatsFilters().has()) {
+ return;
+ }
+ const auto history = _history ? _history() : nullptr;
+ if (!history || history->peer->id != data.fromPeerId) {
+ return;
+ }
+ const auto peerId = data.joinedPeerId;
+ if (const auto peer = _controller->session().data().peer(peerId)) {
+ showChannelFilterToast(peer);
+ }
+ }, _lifetime);
}
void SelfForwardsTagger::showSelectorForMessages(
@@ -336,6 +354,91 @@ void SelfForwardsTagger::showTaggedToast(DocumentId reaction) {
}
}
+void SelfForwardsTagger::showChannelFilterToast(not_null peer) {
+ hideToast();
+ const auto toastText = peer->isChannel() && !peer->isMegagroup()
+ ? tr::lng_add_channel_to_filter_selector(tr::now)
+ : tr::lng_add_group_to_filter_selector(tr::now);
+ _toast = Ui::Toast::Show(_scroll, Ui::Toast::Config{
+ .text = { .text = toastText },
+ .st = &st::joinChatAddToFilterToast,
+ .attach = RectPart::Top,
+ .acceptinput = true,
+ .infinite = true,
+ });
+ if (const auto strong = _toast.get()) {
+ const auto widget = strong->widget();
+ createLottieIcon(widget, u"toast/chats_filter_in"_q);
+ const auto rightButton = createRightButton(widget);
+ const auto history = peer->owner().history(peer);
+
+ struct State {
+ rpl::lifetime timerLifetime;
+ bool menuExpanded = false;
+ };
+ const auto state = widget->lifetime().make_state();
+ const auto restartTimer = [=](crl::time ms) {
+ state->timerLifetime.destroy();
+ base::timer_once(ms) | rpl::start_with_next([=] {
+ hideToast();
+ }, state->timerLifetime);
+ };
+
+ rightButton->setClickedCallback([=] {
+ state->menuExpanded = true;
+ state->timerLifetime.destroy();
+ const auto menu = Ui::CreateChild(
+ rightButton,
+ st::foldersMenu);
+ menu->setForcedOrigin(Ui::PanelAnimation::Origin::TopRight);
+ FillChooseFilterMenu(_controller, menu, history);
+ if (!menu->empty()) {
+ menu->popup(
+ rightButton->mapToGlobal(
+ QPoint(
+ rightButton->width(),
+ rightButton->height() + rightButton->y())));
+ QObject::connect(menu, &QObject::destroyed, [=] {
+ hideToast();
+ });
+ } else {
+ hideToast();
+ }
+ });
+
+ base::install_event_filter(widget, [=](not_null event) {
+ if (event->type() == QEvent::MouseButtonPress) {
+ state->timerLifetime.destroy();
+ return base::EventFilterResult::Continue;
+ } else if (!state->menuExpanded && event->type() == QEvent::Enter) {
+ state->timerLifetime.destroy();
+ return base::EventFilterResult::Continue;
+ } else if (!state->menuExpanded && event->type() == QEvent::Leave) {
+ restartTimer(kTimerOnLeave);
+ return base::EventFilterResult::Continue;
+ }
+ return base::EventFilterResult::Continue;
+ }, widget->lifetime());
+
+ restartTimer(kInitTimer);
+ }
+}
+
+not_null SelfForwardsTagger::createRightButton(
+ not_null widget) {
+ const auto button = Ui::CreateChild(
+ widget.get(),
+ st::joinChatAddToFilterToastButton);
+ widget->sizeValue() | rpl::start_with_next([=](const QSize &size) {
+ button->moveToRight(
+ st::lineWidth * 4,
+ (size.height() - button->height()) / 2);
+ }, button->lifetime());
+
+ button->show();
+ return button;
+}
+
void SelfForwardsTagger::hideToast() {
if (const auto strong = _toast.get()) {
strong->hideAnimated();
diff --git a/Telegram/SourceFiles/history/view/history_view_self_forwards_tagger.h b/Telegram/SourceFiles/history/view/history_view_self_forwards_tagger.h
index df340472dc..53e5ca4e1f 100644
--- a/Telegram/SourceFiles/history/view/history_view_self_forwards_tagger.h
+++ b/Telegram/SourceFiles/history/view/history_view_self_forwards_tagger.h
@@ -29,6 +29,7 @@ class SessionController;
namespace Ui {
class RpWidget;
+class AbstractButton;
} // namespace Ui
namespace Ui::Toast {
@@ -57,7 +58,10 @@ private:
void showSelectorForMessages(const MessageIdsList &ids);
void showToast(const TextWithEntities &text, Fn callback);
void showTaggedToast(DocumentId);
+ void showChannelFilterToast(not_null peer);
void createLottieIcon(not_null widget, const QString &name);
+ not_null createRightButton(
+ not_null widget);
void hideToast();
[[nodiscard]] QRect toastGeometry() const;