diff --git a/Telegram/Resources/animations/profile/profile_muting.tgs b/Telegram/Resources/animations/profile/profile_muting.tgs
new file mode 100644
index 0000000000..bdae1b5f90
Binary files /dev/null and b/Telegram/Resources/animations/profile/profile_muting.tgs differ
diff --git a/Telegram/Resources/animations/profile/profile_unmuting.tgs b/Telegram/Resources/animations/profile/profile_unmuting.tgs
new file mode 100644
index 0000000000..a1dd834d6c
Binary files /dev/null and b/Telegram/Resources/animations/profile/profile_unmuting.tgs differ
diff --git a/Telegram/Resources/icons/profile/message.svg b/Telegram/Resources/icons/profile/message.svg
new file mode 100644
index 0000000000..685cf25a68
--- /dev/null
+++ b/Telegram/Resources/icons/profile/message.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/mute.svg b/Telegram/Resources/icons/profile/mute.svg
new file mode 100644
index 0000000000..d9fea015ed
--- /dev/null
+++ b/Telegram/Resources/icons/profile/mute.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/icons/profile/unmute.svg b/Telegram/Resources/icons/profile/unmute.svg
new file mode 100644
index 0000000000..80bd6c2fa4
--- /dev/null
+++ b/Telegram/Resources/icons/profile/unmute.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index e85ef8d93b..90d0250fb9 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -1668,6 +1668,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_changed_photo_title" = "Photo updated";
"lng_profile_changed_photo_about" = "You can change it in {link}.";
"lng_profile_changed_photo_link" = "Settings";
+
+"lng_profile_action_short_message" = "Message";
+"lng_profile_action_short_mute" = "Mute";
+"lng_profile_action_short_unmute" = "Unmute";
+
"lng_media_type_photos" = "Photos";
"lng_media_type_gifs" = "GIFs";
"lng_media_type_videos" = "Videos";
diff --git a/Telegram/Resources/qrc/telegram/animations.qrc b/Telegram/Resources/qrc/telegram/animations.qrc
index 363c9e924a..42b1da8e3a 100644
--- a/Telegram/Resources/qrc/telegram/animations.qrc
+++ b/Telegram/Resources/qrc/telegram/animations.qrc
@@ -46,6 +46,9 @@
../../animations/toast/saved_messages.tgs
../../animations/toast/tagged.tgs
+ ../../animations/profile/profile_muting.tgs
+ ../../animations/profile/profile_unmuting.tgs
+
../../animations/dice/dice_idle.tgs
../../animations/dice/dart_idle.tgs
../../animations/dice/bball_idle.tgs
diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style
index bef4b76cd3..2a937e3e4a 100644
--- a/Telegram/SourceFiles/info/info.style
+++ b/Telegram/SourceFiles/info/info.style
@@ -368,10 +368,15 @@ infoProfileTopBarActionButtonTextSkip: 4px;
infoProfileTopBarActionButtonsPadding: margins(12px, 6px, 12px, 12px);
infoProfileTopBarActionButtonsHeight: infoProfileTopBarActionButtonSize + infoProfileTopBarActionButtonsPadding.topBottom;
+infoProfileTopBarActionButtonsSpace: 10px;
infoProfileTopBarStep2: infoProfileTopBarHeightMax - infoLayerTopBarHeight;
infoProfileTopBarStep1: infoProfileTopBarStep2 - infoProfileTopBarActionButtonsHeight;
+infoProfileTopBarActionMessage: icon{{ "profile/message-22x22", premiumButtonFg }};
+infoProfileTopBarActionMute: icon{{ "profile/mute-22x22", premiumButtonFg }};
+infoProfileTopBarActionUnmute: icon{{ "profile/unmute-22x22", premiumButtonFg }};
+
infoMinimalWidth: 324px;
infoDesiredWidth: 392px;
infoMinimalLayerMargin: 48px;
diff --git a/Telegram/SourceFiles/info/profile/info_profile_top_bar.cpp b/Telegram/SourceFiles/info/profile/info_profile_top_bar.cpp
index 3a33a856f9..3f8b7d1930 100644
--- a/Telegram/SourceFiles/info/profile/info_profile_top_bar.cpp
+++ b/Telegram/SourceFiles/info/profile/info_profile_top_bar.cpp
@@ -29,7 +29,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_saved_sublist.h"
#include "data/data_session.h"
#include "data/data_user.h"
+#include "data/notify/data_notify_settings.h"
+#include "data/notify/data_peer_notify_settings.h"
#include "data/stickers/data_custom_emoji.h"
+#include "history/history.h"
#include "info_profile_actions.h"
#include "info/info_controller.h"
#include "info/info_memento.h"
@@ -37,11 +40,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_badge.h"
#include "info/profile/info_profile_cover.h" // LargeCustomEmojiMargins
#include "info/profile/info_profile_status_label.h"
+#include "info/profile/info_profile_top_bar_action_button.h"
#include "info/profile/info_profile_values.h"
#include "lang/lang_keys.h"
#include "lottie/lottie_animation.h"
#include "lottie/lottie_multi_player.h"
#include "main/main_session.h"
+#include "menu/menu_mute.h"
#include "settings/settings_premium.h"
#include "ui/boxes/show_or_premium_box.h"
#include "ui/color_contrast.h"
@@ -55,7 +60,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/top_background_gradient.h"
#include "ui/ui_utility.h"
#include "ui/widgets/buttons.h"
-#include "ui/widgets/buttons.h"
+#include "ui/widgets/horizontal_fit_container.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "ui/widgets/popup_menu.h"
@@ -261,6 +266,7 @@ TopBar::TopBar(
setupButtons(controller, descriptor.backToggles.value());
setupUserpicButton(controller);
setupPinnedToTopGifts();
+ setupActions(controller);
if (_topic) {
_topicIconView = std::make_unique(
_topic,
@@ -318,6 +324,107 @@ TopBar::TopBar(
}, lifetime());
}
+void TopBar::setupActions(not_null controller) {
+ const auto peer = controller->key().peer();
+ const auto user = peer->asUser();
+ const auto channel = peer->asChannel();
+ const auto chat = peer->asChat();
+ const auto topic = controller->key().topic();
+ _actions = base::make_unique_q(
+ this,
+ st::infoProfileTopBarActionButtonsSpace);
+ if (user) {
+ const auto message = Ui::CreateChild(
+ this,
+ tr::lng_profile_action_short_message(tr::now),
+ st::infoProfileTopBarActionMessage);
+ message->setClickedCallback([=, window = controller] {
+ window->showPeerHistory(
+ peer->id,
+ Window::SectionShow::Way::Forward);
+ });
+ _actions->add(message);
+ }
+ {
+ const auto notifications = Ui::CreateChild(
+ this,
+ tr::lng_profile_action_short_mute(tr::now),
+ st::infoProfileTopBarActionMessage);
+ notifications->convertToToggle(
+ st::infoProfileTopBarActionUnmute,
+ st::infoProfileTopBarActionMute,
+ u"profile_muting"_q,
+ u"profile_unmuting"_q);
+
+ const auto topicRootId = topic ? topic->rootId() : MsgId();
+ const auto makeThread = [=] {
+ return topicRootId
+ ? static_cast(peer->forumTopicFor(topicRootId))
+ : peer->owner().history(peer).get();
+ };
+ (topic
+ ? NotificationsEnabledValue(topic)
+ : NotificationsEnabledValue(peer)
+ ) | rpl::start_with_next([=](bool enabled) {
+ notifications->toggle(enabled);
+ notifications->setText(enabled
+ ? tr::lng_profile_action_short_mute(tr::now)
+ : tr::lng_profile_action_short_unmute(tr::now));
+ }, notifications->lifetime());
+ notifications->finishAnimating();
+
+ notifications->setAcceptBoth();
+ const auto notifySettings = &peer->owner().notifySettings();
+ MuteMenu::SetupMuteMenu(
+ notifications,
+ notifications->clicks(
+ ) | rpl::filter([=](Qt::MouseButton button) {
+ if (button == Qt::RightButton) {
+ return true;
+ }
+ const auto topic = topicRootId
+ ? peer->forumTopicFor(topicRootId)
+ : nullptr;
+ Assert(!topicRootId || topic != nullptr);
+ const auto is = topic
+ ? notifySettings->isMuted(topic)
+ : notifySettings->isMuted(peer);
+ if (is) {
+ if (topic) {
+ notifySettings->update(topic, { .unmute = true });
+ } else {
+ notifySettings->update(peer, { .unmute = true });
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }) | rpl::to_empty,
+ makeThread,
+ controller->uiShow());
+ _actions->add(notifications);
+ }
+ const auto padding = st::infoProfileTopBarActionButtonsPadding;
+ sizeValue() | rpl::start_with_next([=](const QSize &size) {
+ const auto ratio = float64(size.height())
+ / (st::infoProfileTopBarActionButtonsHeight
+ + st::infoLayerTopBarHeight);
+ const auto h = st::infoProfileTopBarActionButtonSize;
+ const auto resultHeight = (ratio >= 1.)
+ ? h
+ : (ratio <= 0.5)
+ ? 0
+ : int(h * (ratio - 0.5) / 0.5);
+ _actions->setGeometry(
+ padding.left(),
+ size.height() - resultHeight - padding.bottom(),
+ size.width() - rect::m::sum::h(padding),
+ resultHeight);
+ }, _actions->lifetime());
+ _actions->show();
+ _actions->raise();
+}
+
void TopBar::setupUserpicButton(not_null controller) {
_userpicButton = base::make_unique_q(this);
rpl::single(
@@ -460,11 +567,15 @@ int TopBar::statusMostLeft() const {
}
void TopBar::updateLabelsPosition() {
- const auto max = QWidget::maximumHeight();
- const auto min = QWidget::minimumHeight();
- _progress = (max > min)
- ? ((height() - min) / float64(max - min))
- : 1.;
+ _progress = [&] {
+ const auto max = QWidget::maximumHeight();
+ const auto min = QWidget::minimumHeight()
+ + st::infoProfileTopBarActionButtonsHeight;
+ const auto p = (max > min)
+ ? ((height() - min) / float64(max - min))
+ : 1.;
+ return std::clamp(p, 0., 1.);
+ }();
const auto progressCurrent = _progress.current();
auto rightButtonsWidth = 0;
diff --git a/Telegram/SourceFiles/info/profile/info_profile_top_bar.h b/Telegram/SourceFiles/info/profile/info_profile_top_bar.h
index c201fd304c..58496a85d6 100644
--- a/Telegram/SourceFiles/info/profile/info_profile_top_bar.h
+++ b/Telegram/SourceFiles/info/profile/info_profile_top_bar.h
@@ -54,6 +54,7 @@ class RoundButton;
class StarsRating;
template
class FadeWrap;
+class HorizontalFitContainer;
} //namespace Ui
namespace Info {
@@ -115,6 +116,7 @@ private:
not_null controller,
const Ui::Menu::MenuCallback &addAction);
void setupUserpicButton(not_null controller);
+ void setupActions(not_null controller);
void setupButtons(
not_null controller,
rpl::producer backToggles);
@@ -178,6 +180,8 @@ private:
base::unique_qptr _userpicButton;
+ base::unique_qptr _actions;
+
std::unique_ptr _lottiePlayer;
struct PinnedToTopGiftEntry {
Lottie::Animation *animation = nullptr;