mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Improve "read time" context menu info design.
This commit is contained in:
parent
474f1118b6
commit
ad03431b0a
10 changed files with 564 additions and 237 deletions
|
@ -55,7 +55,6 @@ constexpr auto kToggleStickerTimeout = 2 * crl::time(1000);
|
||||||
constexpr auto kStarOpacityOff = 0.1;
|
constexpr auto kStarOpacityOff = 0.1;
|
||||||
constexpr auto kStarOpacityOn = 1.;
|
constexpr auto kStarOpacityOn = 1.;
|
||||||
constexpr auto kStarPeriod = 3 * crl::time(1000);
|
constexpr auto kStarPeriod = 3 * crl::time(1000);
|
||||||
constexpr auto kShowOrLineOpacity = 0.3;
|
|
||||||
|
|
||||||
using Data::ReactionId;
|
using Data::ReactionId;
|
||||||
|
|
||||||
|
@ -1316,200 +1315,6 @@ void PremiumUnavailableBox(not_null<Ui::GenericBox*> box) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] object_ptr<Ui::RpWidget> MakeShowOrPremiumIcon(
|
|
||||||
not_null<Ui::RpWidget*> parent,
|
|
||||||
not_null<const style::icon*> icon) {
|
|
||||||
const auto margin = st::showOrIconMargin;
|
|
||||||
const auto padding = st::showOrIconPadding;
|
|
||||||
const auto inner = padding.top() + icon->height() + padding.bottom();
|
|
||||||
const auto full = margin.top() + inner + margin.bottom();
|
|
||||||
auto result = object_ptr<Ui::FixedHeightWidget>(parent, full);
|
|
||||||
const auto raw = result.data();
|
|
||||||
|
|
||||||
raw->resize(st::boxWideWidth, full);
|
|
||||||
raw->paintRequest(
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
auto p = QPainter(raw);
|
|
||||||
auto hq = PainterHighQualityEnabler(p);
|
|
||||||
const auto width = raw->width();
|
|
||||||
const auto position = QPoint((width - inner) / 2, margin.top());
|
|
||||||
const auto rect = QRect(position, QSize(inner, inner));
|
|
||||||
const auto shift = QPoint(padding.left(), padding.top());
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.setBrush(st::showOrIconBg);
|
|
||||||
p.drawEllipse(rect);
|
|
||||||
icon->paint(p, position + shift, width);
|
|
||||||
}, raw->lifetime());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] object_ptr<Ui::RpWidget> MakeShowOrLabel(
|
|
||||||
not_null<Ui::RpWidget*> parent,
|
|
||||||
rpl::producer<QString> text) {
|
|
||||||
auto result = object_ptr<Ui::FlatLabel>(
|
|
||||||
parent,
|
|
||||||
std::move(text),
|
|
||||||
st::showOrLabel);
|
|
||||||
const auto raw = result.data();
|
|
||||||
|
|
||||||
raw->paintRequest(
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
auto p = QPainter(raw);
|
|
||||||
|
|
||||||
const auto full = st::showOrLineWidth;
|
|
||||||
const auto left = (raw->width() - full) / 2;
|
|
||||||
const auto text = raw->textMaxWidth() + 2 * st::showOrLabelSkip;
|
|
||||||
const auto fill = (full - text) / 2;
|
|
||||||
const auto stroke = st::lineWidth;
|
|
||||||
const auto top = st::showOrLineTop;
|
|
||||||
p.setOpacity(kShowOrLineOpacity);
|
|
||||||
p.fillRect(left, top, fill, stroke, st::windowSubTextFg);
|
|
||||||
const auto start = left + full - fill;
|
|
||||||
p.fillRect(start, top, fill, stroke, st::windowSubTextFg);
|
|
||||||
}, raw->lifetime());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShowOrPremiumBox(
|
|
||||||
not_null<Ui::GenericBox*> box,
|
|
||||||
ShowOrPremium type,
|
|
||||||
QString shortName,
|
|
||||||
Fn<void()> justShow,
|
|
||||||
Fn<void()> toPremium) {
|
|
||||||
struct Skin {
|
|
||||||
rpl::producer<QString> showTitle;
|
|
||||||
rpl::producer<TextWithEntities> showAbout;
|
|
||||||
rpl::producer<QString> showButton;
|
|
||||||
rpl::producer<QString> orPremium;
|
|
||||||
rpl::producer<QString> premiumTitle;
|
|
||||||
rpl::producer<TextWithEntities> premiumAbout;
|
|
||||||
rpl::producer<QString> premiumButton;
|
|
||||||
QString toast;
|
|
||||||
const style::icon *icon = nullptr;
|
|
||||||
};
|
|
||||||
auto skin = (type == ShowOrPremium::LastSeen)
|
|
||||||
? Skin{
|
|
||||||
tr::lng_lastseen_show_title(),
|
|
||||||
tr::lng_lastseen_show_about(
|
|
||||||
lt_user,
|
|
||||||
rpl::single(TextWithEntities{ shortName }),
|
|
||||||
Ui::Text::RichLangValue),
|
|
||||||
tr::lng_lastseen_show_button(),
|
|
||||||
tr::lng_lastseen_or(),
|
|
||||||
tr::lng_lastseen_premium_title(),
|
|
||||||
tr::lng_lastseen_premium_about(
|
|
||||||
lt_user,
|
|
||||||
rpl::single(TextWithEntities{ shortName }),
|
|
||||||
Ui::Text::RichLangValue),
|
|
||||||
tr::lng_lastseen_premium_button(),
|
|
||||||
tr::lng_lastseen_shown_toast(tr::now),
|
|
||||||
&st::showOrIconLastSeen,
|
|
||||||
}
|
|
||||||
: (type == ShowOrPremium::ReadTime)
|
|
||||||
? Skin{
|
|
||||||
tr::lng_readtime_show_title(),
|
|
||||||
tr::lng_readtime_show_about(
|
|
||||||
lt_user,
|
|
||||||
rpl::single(TextWithEntities{ shortName }),
|
|
||||||
Ui::Text::RichLangValue),
|
|
||||||
tr::lng_readtime_show_button(),
|
|
||||||
tr::lng_readtime_or(),
|
|
||||||
tr::lng_readtime_premium_title(),
|
|
||||||
tr::lng_readtime_premium_about(
|
|
||||||
lt_user,
|
|
||||||
rpl::single(TextWithEntities{ shortName }),
|
|
||||||
Ui::Text::RichLangValue),
|
|
||||||
tr::lng_readtime_premium_button(),
|
|
||||||
tr::lng_readtime_shown_toast(tr::now),
|
|
||||||
&st::showOrIconReadTime,
|
|
||||||
}
|
|
||||||
: Skin();
|
|
||||||
|
|
||||||
box->setStyle(st::showOrBox);
|
|
||||||
box->setWidth(st::boxWideWidth);
|
|
||||||
box->addTopButton(st::boxTitleClose, [=] {
|
|
||||||
box->closeBox();
|
|
||||||
});
|
|
||||||
|
|
||||||
box->addRow(MakeShowOrPremiumIcon(box, skin.icon));
|
|
||||||
box->addRow(
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
box,
|
|
||||||
std::move(skin.showTitle),
|
|
||||||
st::boostCenteredTitle),
|
|
||||||
st::showOrTitlePadding);
|
|
||||||
box->addRow(
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
box,
|
|
||||||
std::move(skin.showAbout),
|
|
||||||
st::boostText),
|
|
||||||
st::showOrAboutPadding);
|
|
||||||
const auto show = box->addRow(
|
|
||||||
object_ptr<Ui::RoundButton>(
|
|
||||||
box,
|
|
||||||
std::move(skin.showButton),
|
|
||||||
st::showOrShowButton),
|
|
||||||
QMargins(
|
|
||||||
st::showOrBox.buttonPadding.left(),
|
|
||||||
0,
|
|
||||||
st::showOrBox.buttonPadding.right(),
|
|
||||||
0));
|
|
||||||
show->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
|
|
||||||
box->addRow(
|
|
||||||
MakeShowOrLabel(box, std::move(skin.orPremium)),
|
|
||||||
st::showOrLabelPadding);
|
|
||||||
box->addRow(
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
box,
|
|
||||||
std::move(skin.premiumTitle),
|
|
||||||
st::boostCenteredTitle),
|
|
||||||
st::showOrTitlePadding);
|
|
||||||
box->addRow(
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
box,
|
|
||||||
std::move(skin.premiumAbout),
|
|
||||||
st::boostText),
|
|
||||||
st::showOrPremiumAboutPadding);
|
|
||||||
|
|
||||||
const auto premium = Ui::CreateChild<Ui::GradientButton>(
|
|
||||||
box.get(),
|
|
||||||
Ui::Premium::ButtonGradientStops());
|
|
||||||
|
|
||||||
const auto &st = st::premiumPreviewBox.button;
|
|
||||||
premium->resize(st::showOrShowButton.width, st::showOrShowButton.height);
|
|
||||||
|
|
||||||
const auto label = Ui::CreateChild<Ui::FlatLabel>(
|
|
||||||
premium,
|
|
||||||
std::move(skin.premiumButton),
|
|
||||||
st::premiumPreviewButtonLabel);
|
|
||||||
label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
||||||
rpl::combine(
|
|
||||||
premium->widthValue(),
|
|
||||||
label->widthValue()
|
|
||||||
) | rpl::start_with_next([=](int outer, int width) {
|
|
||||||
label->moveToLeft(
|
|
||||||
(outer - width) / 2,
|
|
||||||
st::premiumPreviewBox.button.textTop,
|
|
||||||
outer);
|
|
||||||
}, label->lifetime());
|
|
||||||
|
|
||||||
box->setShowFinishedCallback([=] {
|
|
||||||
premium->startGlareAnimation();
|
|
||||||
});
|
|
||||||
|
|
||||||
box->addButton(
|
|
||||||
object_ptr<Ui::AbstractButton>::fromRaw(premium));
|
|
||||||
|
|
||||||
show->setClickedCallback([box, justShow, toast = skin.toast] {
|
|
||||||
justShow();
|
|
||||||
box->uiShow()->showToast(toast);
|
|
||||||
box->closeBox();
|
|
||||||
});
|
|
||||||
premium->setClickedCallback(std::move(toPremium));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoubledLimitsPreviewBox(
|
void DoubledLimitsPreviewBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
not_null<Main::Session*> session) {
|
not_null<Main::Session*> session) {
|
||||||
|
|
|
@ -83,17 +83,6 @@ void ShowPremiumPreviewToBuy(
|
||||||
|
|
||||||
void PremiumUnavailableBox(not_null<Ui::GenericBox*> box);
|
void PremiumUnavailableBox(not_null<Ui::GenericBox*> box);
|
||||||
|
|
||||||
enum class ShowOrPremium : uchar {
|
|
||||||
LastSeen,
|
|
||||||
ReadTime,
|
|
||||||
};
|
|
||||||
void ShowOrPremiumBox(
|
|
||||||
not_null<Ui::GenericBox*> box,
|
|
||||||
ShowOrPremium type,
|
|
||||||
QString shortName,
|
|
||||||
Fn<void()> justShow,
|
|
||||||
Fn<void()> toPremium);
|
|
||||||
|
|
||||||
[[nodiscard]] object_ptr<Ui::GradientButton> CreateUnlockButton(
|
[[nodiscard]] object_ptr<Ui::GradientButton> CreateUnlockButton(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
rpl::producer<QString> text);
|
rpl::producer<QString> text);
|
||||||
|
|
|
@ -249,6 +249,13 @@ defaultWhoRead: WhoRead {
|
||||||
iconPosition: point(15px, 7px);
|
iconPosition: point(15px, 7px);
|
||||||
itemPadding: margins(44px, 9px, 17px, 7px);
|
itemPadding: margins(44px, 9px, 17px, 7px);
|
||||||
}
|
}
|
||||||
|
whenReadStyle: TextStyle(defaultTextStyle) {
|
||||||
|
font: font(12px);
|
||||||
|
}
|
||||||
|
whenReadPadding: margins(34px, 3px, 17px, 4px);
|
||||||
|
whenReadIconPosition: point(8px, 0px);
|
||||||
|
whenReadSkip: 3px;
|
||||||
|
whenReadShowPadding: margins(6px, 0px, 6px, 2px);
|
||||||
|
|
||||||
switchPmButton: RoundButton(defaultBoxButton) {
|
switchPmButton: RoundButton(defaultBoxButton) {
|
||||||
width: 320px;
|
width: 320px;
|
||||||
|
|
|
@ -40,9 +40,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "menu/menu_item_download_files.h"
|
#include "menu/menu_item_download_files.h"
|
||||||
#include "menu/menu_send.h"
|
#include "menu/menu_send.h"
|
||||||
#include "ui/boxes/confirm_box.h"
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
#include "ui/boxes/show_or_premium_box.h"
|
||||||
#include "boxes/delete_messages_box.h"
|
#include "boxes/delete_messages_box.h"
|
||||||
#include "boxes/report_messages_box.h"
|
#include "boxes/report_messages_box.h"
|
||||||
#include "boxes/premium_preview_box.h"
|
|
||||||
#include "boxes/sticker_set_box.h"
|
#include "boxes/sticker_set_box.h"
|
||||||
#include "boxes/stickers_box.h"
|
#include "boxes/stickers_box.h"
|
||||||
#include "boxes/translate_box.h"
|
#include "boxes/translate_box.h"
|
||||||
|
@ -1269,22 +1269,25 @@ void AddWhoReactedAction(
|
||||||
const auto whoReadIds = std::make_shared<Api::WhoReadList>();
|
const auto whoReadIds = std::make_shared<Api::WhoReadList>();
|
||||||
const auto weak = Ui::MakeWeak(menu.get());
|
const auto weak = Ui::MakeWeak(menu.get());
|
||||||
const auto user = item->history()->peer;
|
const auto user = item->history()->peer;
|
||||||
|
const auto showOrPremium = [=] {
|
||||||
|
if (const auto strong = weak.data()) {
|
||||||
|
strong->hideMenu();
|
||||||
|
}
|
||||||
|
const auto type = Ui::ShowOrPremium::ReadTime;
|
||||||
|
const auto name = user->shortName();
|
||||||
|
auto box = Box(Ui::ShowOrPremiumBox, type, name, [=] {
|
||||||
|
const auto api = &controller->session().api();
|
||||||
|
api->globalPrivacy().updateHideReadTime({});
|
||||||
|
}, [=] {
|
||||||
|
Settings::ShowPremium(controller, u"revtime_hidden"_q);
|
||||||
|
});
|
||||||
|
controller->show(std::move(box));
|
||||||
|
};
|
||||||
const auto participantChosen = [=](uint64 id) {
|
const auto participantChosen = [=](uint64 id) {
|
||||||
if (const auto strong = weak.data()) {
|
if (const auto strong = weak.data()) {
|
||||||
strong->hideMenu();
|
strong->hideMenu();
|
||||||
}
|
}
|
||||||
if (id) {
|
controller->showPeerInfo(PeerId(id));
|
||||||
controller->showPeerInfo(PeerId(id));
|
|
||||||
} else {
|
|
||||||
const auto type = ShowOrPremium::ReadTime;
|
|
||||||
auto box = Box(ShowOrPremiumBox, type, user->shortName(), [=] {
|
|
||||||
const auto api = &controller->session().api();
|
|
||||||
api->globalPrivacy().updateHideReadTime({});
|
|
||||||
}, [=] {
|
|
||||||
Settings::ShowPremium(controller, u"revtime_hidden"_q);
|
|
||||||
});
|
|
||||||
controller->show(std::move(box));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const auto showAllChosen = [=, itemId = item->fullId()]{
|
const auto showAllChosen = [=, itemId = item->fullId()]{
|
||||||
// Pressing on an item that has a submenu doesn't hide it :(
|
// Pressing on an item that has a submenu doesn't hide it :(
|
||||||
|
@ -1302,12 +1305,19 @@ void AddWhoReactedAction(
|
||||||
if (!menu->empty()) {
|
if (!menu->empty()) {
|
||||||
menu->addSeparator(&st::expandedMenuSeparator);
|
menu->addSeparator(&st::expandedMenuSeparator);
|
||||||
}
|
}
|
||||||
menu->addAction(Ui::WhoReactedContextAction(
|
if (item->history()->peer->isUser()) {
|
||||||
menu.get(),
|
menu->addAction(Ui::WhenReadContextAction(
|
||||||
Api::WhoReacted(item, context, st::defaultWhoRead, whoReadIds),
|
menu.get(),
|
||||||
Data::ReactedMenuFactory(&controller->session()),
|
Api::WhoReacted(item, context, st::defaultWhoRead, whoReadIds),
|
||||||
participantChosen,
|
showOrPremium));
|
||||||
showAllChosen));
|
} else {
|
||||||
|
menu->addAction(Ui::WhoReactedContextAction(
|
||||||
|
menu.get(),
|
||||||
|
Api::WhoReacted(item, context, st::defaultWhoRead, whoReadIds),
|
||||||
|
Data::ReactedMenuFactory(&controller->session()),
|
||||||
|
participantChosen,
|
||||||
|
showAllChosen));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowTagMenu(
|
void ShowTagMenu(
|
||||||
|
|
|
@ -24,9 +24,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/profile/info_profile_emoji_status_panel.h"
|
#include "info/profile/info_profile_emoji_status_panel.h"
|
||||||
#include "info/info_controller.h"
|
#include "info/info_controller.h"
|
||||||
#include "boxes/peers/edit_forum_topic_box.h"
|
#include "boxes/peers/edit_forum_topic_box.h"
|
||||||
#include "boxes/premium_preview_box.h"
|
|
||||||
#include "history/view/media/history_view_sticker_player.h"
|
#include "history/view/media/history_view_sticker_player.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
#include "ui/boxes/show_or_premium_box.h"
|
||||||
#include "ui/controls/userpic_button.h"
|
#include "ui/controls/userpic_button.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
@ -414,8 +414,8 @@ void Cover::setupShowLastSeen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_showLastSeen->setClickedCallback([=] {
|
_showLastSeen->setClickedCallback([=] {
|
||||||
const auto type = ShowOrPremium::LastSeen;
|
const auto type = Ui::ShowOrPremium::LastSeen;
|
||||||
auto box = Box(ShowOrPremiumBox, type, user->shortName(), [=] {
|
auto box = Box(Ui::ShowOrPremiumBox, type, user->shortName(), [=] {
|
||||||
_controller->session().api().userPrivacy().save(
|
_controller->session().api().userPrivacy().save(
|
||||||
::Api::UserPrivacy::Key::LastSeen,
|
::Api::UserPrivacy::Key::LastSeen,
|
||||||
{});
|
{});
|
||||||
|
|
223
Telegram/SourceFiles/ui/boxes/show_or_premium_box.cpp
Normal file
223
Telegram/SourceFiles/ui/boxes/show_or_premium_box.cpp
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
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 "ui/boxes/show_or_premium_box.h"
|
||||||
|
|
||||||
|
#include "base/object_ptr.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "ui/effects/premium_graphics.h"
|
||||||
|
#include "ui/layers/generic_box.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "ui/widgets/gradient_round_button.h"
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/painter.h"
|
||||||
|
#include "styles/style_layers.h"
|
||||||
|
#include "styles/style_premium.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kShowOrLineOpacity = 0.3;
|
||||||
|
|
||||||
|
[[nodiscard]] object_ptr<RpWidget> MakeShowOrPremiumIcon(
|
||||||
|
not_null<RpWidget*> parent,
|
||||||
|
not_null<const style::icon*> icon) {
|
||||||
|
const auto margin = st::showOrIconMargin;
|
||||||
|
const auto padding = st::showOrIconPadding;
|
||||||
|
const auto inner = padding.top() + icon->height() + padding.bottom();
|
||||||
|
const auto full = margin.top() + inner + margin.bottom();
|
||||||
|
auto result = object_ptr<FixedHeightWidget>(parent, full);
|
||||||
|
const auto raw = result.data();
|
||||||
|
|
||||||
|
raw->resize(st::boxWideWidth, full);
|
||||||
|
raw->paintRequest(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
auto p = QPainter(raw);
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
const auto width = raw->width();
|
||||||
|
const auto position = QPoint((width - inner) / 2, margin.top());
|
||||||
|
const auto rect = QRect(position, QSize(inner, inner));
|
||||||
|
const auto shift = QPoint(padding.left(), padding.top());
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(st::showOrIconBg);
|
||||||
|
p.drawEllipse(rect);
|
||||||
|
icon->paint(p, position + shift, width);
|
||||||
|
}, raw->lifetime());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] object_ptr<RpWidget> MakeShowOrLabel(
|
||||||
|
not_null<RpWidget*> parent,
|
||||||
|
rpl::producer<QString> text) {
|
||||||
|
auto result = object_ptr<FlatLabel>(
|
||||||
|
parent,
|
||||||
|
std::move(text),
|
||||||
|
st::showOrLabel);
|
||||||
|
const auto raw = result.data();
|
||||||
|
|
||||||
|
raw->paintRequest(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
auto p = QPainter(raw);
|
||||||
|
|
||||||
|
const auto full = st::showOrLineWidth;
|
||||||
|
const auto left = (raw->width() - full) / 2;
|
||||||
|
const auto text = raw->textMaxWidth() + 2 * st::showOrLabelSkip;
|
||||||
|
const auto fill = (full - text) / 2;
|
||||||
|
const auto stroke = st::lineWidth;
|
||||||
|
const auto top = st::showOrLineTop;
|
||||||
|
p.setOpacity(kShowOrLineOpacity);
|
||||||
|
p.fillRect(left, top, fill, stroke, st::windowSubTextFg);
|
||||||
|
const auto start = left + full - fill;
|
||||||
|
p.fillRect(start, top, fill, stroke, st::windowSubTextFg);
|
||||||
|
}, raw->lifetime());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void ShowOrPremiumBox(
|
||||||
|
not_null<GenericBox*> box,
|
||||||
|
ShowOrPremium type,
|
||||||
|
QString shortName,
|
||||||
|
Fn<void()> justShow,
|
||||||
|
Fn<void()> toPremium) {
|
||||||
|
struct Skin {
|
||||||
|
rpl::producer<QString> showTitle;
|
||||||
|
rpl::producer<TextWithEntities> showAbout;
|
||||||
|
rpl::producer<QString> showButton;
|
||||||
|
rpl::producer<QString> orPremium;
|
||||||
|
rpl::producer<QString> premiumTitle;
|
||||||
|
rpl::producer<TextWithEntities> premiumAbout;
|
||||||
|
rpl::producer<QString> premiumButton;
|
||||||
|
QString toast;
|
||||||
|
const style::icon *icon = nullptr;
|
||||||
|
};
|
||||||
|
auto skin = (type == ShowOrPremium::LastSeen)
|
||||||
|
? Skin{
|
||||||
|
tr::lng_lastseen_show_title(),
|
||||||
|
tr::lng_lastseen_show_about(
|
||||||
|
lt_user,
|
||||||
|
rpl::single(TextWithEntities{ shortName }),
|
||||||
|
Text::RichLangValue),
|
||||||
|
tr::lng_lastseen_show_button(),
|
||||||
|
tr::lng_lastseen_or(),
|
||||||
|
tr::lng_lastseen_premium_title(),
|
||||||
|
tr::lng_lastseen_premium_about(
|
||||||
|
lt_user,
|
||||||
|
rpl::single(TextWithEntities{ shortName }),
|
||||||
|
Text::RichLangValue),
|
||||||
|
tr::lng_lastseen_premium_button(),
|
||||||
|
tr::lng_lastseen_shown_toast(tr::now),
|
||||||
|
&st::showOrIconLastSeen,
|
||||||
|
}
|
||||||
|
: (type == ShowOrPremium::ReadTime)
|
||||||
|
? Skin{
|
||||||
|
tr::lng_readtime_show_title(),
|
||||||
|
tr::lng_readtime_show_about(
|
||||||
|
lt_user,
|
||||||
|
rpl::single(TextWithEntities{ shortName }),
|
||||||
|
Text::RichLangValue),
|
||||||
|
tr::lng_readtime_show_button(),
|
||||||
|
tr::lng_readtime_or(),
|
||||||
|
tr::lng_readtime_premium_title(),
|
||||||
|
tr::lng_readtime_premium_about(
|
||||||
|
lt_user,
|
||||||
|
rpl::single(TextWithEntities{ shortName }),
|
||||||
|
Text::RichLangValue),
|
||||||
|
tr::lng_readtime_premium_button(),
|
||||||
|
tr::lng_readtime_shown_toast(tr::now),
|
||||||
|
&st::showOrIconReadTime,
|
||||||
|
}
|
||||||
|
: Skin();
|
||||||
|
|
||||||
|
box->setStyle(st::showOrBox);
|
||||||
|
box->setWidth(st::boxWideWidth);
|
||||||
|
box->addTopButton(st::boxTitleClose, [=] {
|
||||||
|
box->closeBox();
|
||||||
|
});
|
||||||
|
|
||||||
|
box->addRow(MakeShowOrPremiumIcon(box, skin.icon));
|
||||||
|
box->addRow(
|
||||||
|
object_ptr<FlatLabel>(
|
||||||
|
box,
|
||||||
|
std::move(skin.showTitle),
|
||||||
|
st::boostCenteredTitle),
|
||||||
|
st::showOrTitlePadding);
|
||||||
|
box->addRow(
|
||||||
|
object_ptr<FlatLabel>(
|
||||||
|
box,
|
||||||
|
std::move(skin.showAbout),
|
||||||
|
st::boostText),
|
||||||
|
st::showOrAboutPadding);
|
||||||
|
const auto show = box->addRow(
|
||||||
|
object_ptr<RoundButton>(
|
||||||
|
box,
|
||||||
|
std::move(skin.showButton),
|
||||||
|
st::showOrShowButton),
|
||||||
|
QMargins(
|
||||||
|
st::showOrBox.buttonPadding.left(),
|
||||||
|
0,
|
||||||
|
st::showOrBox.buttonPadding.right(),
|
||||||
|
0));
|
||||||
|
show->setTextTransform(RoundButton::TextTransform::NoTransform);
|
||||||
|
box->addRow(
|
||||||
|
MakeShowOrLabel(box, std::move(skin.orPremium)),
|
||||||
|
st::showOrLabelPadding);
|
||||||
|
box->addRow(
|
||||||
|
object_ptr<FlatLabel>(
|
||||||
|
box,
|
||||||
|
std::move(skin.premiumTitle),
|
||||||
|
st::boostCenteredTitle),
|
||||||
|
st::showOrTitlePadding);
|
||||||
|
box->addRow(
|
||||||
|
object_ptr<FlatLabel>(
|
||||||
|
box,
|
||||||
|
std::move(skin.premiumAbout),
|
||||||
|
st::boostText),
|
||||||
|
st::showOrPremiumAboutPadding);
|
||||||
|
|
||||||
|
const auto premium = CreateChild<GradientButton>(
|
||||||
|
box.get(),
|
||||||
|
Premium::ButtonGradientStops());
|
||||||
|
|
||||||
|
const auto &st = st::premiumPreviewBox.button;
|
||||||
|
premium->resize(st::showOrShowButton.width, st::showOrShowButton.height);
|
||||||
|
|
||||||
|
const auto label = CreateChild<FlatLabel>(
|
||||||
|
premium,
|
||||||
|
std::move(skin.premiumButton),
|
||||||
|
st::premiumPreviewButtonLabel);
|
||||||
|
label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
rpl::combine(
|
||||||
|
premium->widthValue(),
|
||||||
|
label->widthValue()
|
||||||
|
) | rpl::start_with_next([=](int outer, int width) {
|
||||||
|
label->moveToLeft(
|
||||||
|
(outer - width) / 2,
|
||||||
|
st::premiumPreviewBox.button.textTop,
|
||||||
|
outer);
|
||||||
|
}, label->lifetime());
|
||||||
|
|
||||||
|
box->setShowFinishedCallback([=] {
|
||||||
|
premium->startGlareAnimation();
|
||||||
|
});
|
||||||
|
|
||||||
|
box->addButton(
|
||||||
|
object_ptr<AbstractButton>::fromRaw(premium));
|
||||||
|
|
||||||
|
show->setClickedCallback([box, justShow, toast = skin.toast] {
|
||||||
|
justShow();
|
||||||
|
box->uiShow()->showToast(toast);
|
||||||
|
box->closeBox();
|
||||||
|
});
|
||||||
|
premium->setClickedCallback(std::move(toPremium));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ui
|
25
Telegram/SourceFiles/ui/boxes/show_or_premium_box.h
Normal file
25
Telegram/SourceFiles/ui/boxes/show_or_premium_box.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
|
enum class ShowOrPremium : uchar {
|
||||||
|
LastSeen,
|
||||||
|
ReadTime,
|
||||||
|
};
|
||||||
|
void ShowOrPremiumBox(
|
||||||
|
not_null<GenericBox*> box,
|
||||||
|
ShowOrPremium type,
|
||||||
|
QString shortName,
|
||||||
|
Fn<void()> justShow,
|
||||||
|
Fn<void()> toPremium);
|
||||||
|
|
||||||
|
} // namespace Ui
|
|
@ -124,6 +124,45 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WhenAction final : public Menu::ItemBase {
|
||||||
|
public:
|
||||||
|
WhenAction(
|
||||||
|
not_null<PopupMenu*> parentMenu,
|
||||||
|
rpl::producer<WhoReadContent> content,
|
||||||
|
Fn<void()> showOrPremium);
|
||||||
|
|
||||||
|
bool isEnabled() const override;
|
||||||
|
not_null<QAction*> action() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QPoint prepareRippleStartPosition() const override;
|
||||||
|
QImage prepareRippleMask() const override;
|
||||||
|
|
||||||
|
int contentHeight() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void paint(Painter &p);
|
||||||
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
|
void resolveMinWidth();
|
||||||
|
void refreshText();
|
||||||
|
void refreshDimensions();
|
||||||
|
|
||||||
|
const not_null<PopupMenu*> _parentMenu;
|
||||||
|
const not_null<QAction*> _dummyAction;
|
||||||
|
const Fn<void()> _showOrPremium;
|
||||||
|
const style::Menu &_st;
|
||||||
|
|
||||||
|
Text::String _text;
|
||||||
|
Text::String _show;
|
||||||
|
QRect _showRect;
|
||||||
|
int _textWidth = 0;
|
||||||
|
const int _height = 0;
|
||||||
|
|
||||||
|
WhoReadContent _content;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
TextParseOptions MenuTextOptions = {
|
TextParseOptions MenuTextOptions = {
|
||||||
TextParseLinks, // flags
|
TextParseLinks, // flags
|
||||||
0, // maxw
|
0, // maxw
|
||||||
|
@ -219,10 +258,6 @@ Action::Action(
|
||||||
if (const auto onstack = _showAllChosen) {
|
if (const auto onstack = _showAllChosen) {
|
||||||
onstack();
|
onstack();
|
||||||
}
|
}
|
||||||
} else if (_content.state == WhoReadState::MyHidden) {
|
|
||||||
if (const auto onstack = _participantChosen) {
|
|
||||||
onstack(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
@ -385,11 +420,6 @@ void Action::refreshText() {
|
||||||
_st.itemStyle,
|
_st.itemStyle,
|
||||||
{ ((_content.state == WhoReadState::Unknown)
|
{ ((_content.state == WhoReadState::Unknown)
|
||||||
? tr::lng_context_seen_loading(tr::now)
|
? tr::lng_context_seen_loading(tr::now)
|
||||||
: (_content.state == WhoReadState::MyHidden)
|
|
||||||
? tr::lng_context_read_show(tr::now)
|
|
||||||
: (_content.state == WhoReadState::HisHidden
|
|
||||||
|| _content.state == WhoReadState::TooOld)
|
|
||||||
? tr::lng_context_read_hidden(tr::now)
|
|
||||||
: (usersCount == 1)
|
: (usersCount == 1)
|
||||||
? _content.participants.front().name
|
? _content.participants.front().name
|
||||||
: (_content.fullReactionsCount > 0
|
: (_content.fullReactionsCount > 0
|
||||||
|
@ -470,6 +500,227 @@ void Action::handleKeyPress(not_null<QKeyEvent*> e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WhenAction::WhenAction(
|
||||||
|
not_null<PopupMenu*> parentMenu,
|
||||||
|
rpl::producer<WhoReadContent> content,
|
||||||
|
Fn<void()> showOrPremium)
|
||||||
|
: ItemBase(parentMenu->menu(), parentMenu->menu()->st())
|
||||||
|
, _parentMenu(parentMenu)
|
||||||
|
, _dummyAction(CreateChild<QAction>(parentMenu->menu().get()))
|
||||||
|
, _showOrPremium(std::move(showOrPremium))
|
||||||
|
, _st(parentMenu->menu()->st())
|
||||||
|
, _height(st::whenReadPadding.top()
|
||||||
|
+ st::whenReadStyle.font->height
|
||||||
|
+ st::whenReadPadding.bottom()) {
|
||||||
|
const auto parent = parentMenu->menu();
|
||||||
|
|
||||||
|
setAcceptBoth(true);
|
||||||
|
initResizeHook(parent->sizeValue());
|
||||||
|
|
||||||
|
std::move(
|
||||||
|
content
|
||||||
|
) | rpl::start_with_next([=](WhoReadContent &&content) {
|
||||||
|
const auto changed = (_content.participants != content.participants)
|
||||||
|
|| (_content.state != content.state);
|
||||||
|
_content = content;
|
||||||
|
refreshText();
|
||||||
|
refreshDimensions();
|
||||||
|
setPointerCursor(isEnabled());
|
||||||
|
_dummyAction->setEnabled(isEnabled());
|
||||||
|
if (!isEnabled()) {
|
||||||
|
setSelected(false);
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
resolveMinWidth();
|
||||||
|
refreshDimensions();
|
||||||
|
|
||||||
|
paintRequest(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
Painter p(this);
|
||||||
|
paint(p);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
clicks(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
if (_content.state == WhoReadState::MyHidden) {
|
||||||
|
if (const auto onstack = _showOrPremium) {
|
||||||
|
onstack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
enableMouseSelecting();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WhenAction::resolveMinWidth() {
|
||||||
|
const auto width = [&](const QString &text) {
|
||||||
|
return st::whenReadStyle.font->width(text);
|
||||||
|
};
|
||||||
|
const auto added = st::whenReadShowPadding.left()
|
||||||
|
+ st::whenReadShowPadding.right();
|
||||||
|
|
||||||
|
const auto sampleDate = QDate::currentDate();
|
||||||
|
const auto sampleTime = QLocale().toString(
|
||||||
|
QTime::currentTime(),
|
||||||
|
QLocale::ShortFormat);
|
||||||
|
const auto maxTextWidth = added + std::max({
|
||||||
|
width(tr::lng_contacts_loading(tr::now)),
|
||||||
|
(width(tr::lng_context_read_hidden(tr::now))
|
||||||
|
+ st::whenReadSkip
|
||||||
|
+ width(tr::lng_context_read_show(tr::now))),
|
||||||
|
width(tr::lng_mediaview_today(tr::now, lt_time, sampleTime)),
|
||||||
|
width(tr::lng_mediaview_yesterday(tr::now, lt_time, sampleTime)),
|
||||||
|
width(tr::lng_mediaview_date_time(
|
||||||
|
tr::now,
|
||||||
|
lt_date,
|
||||||
|
tr::lng_month_day(
|
||||||
|
tr::now,
|
||||||
|
lt_month,
|
||||||
|
Lang::MonthDay(sampleDate.month())(tr::now),
|
||||||
|
lt_day,
|
||||||
|
QString::number(sampleDate.day())),
|
||||||
|
lt_time,
|
||||||
|
sampleTime)),
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto maxWidth = st::whenReadPadding.left()
|
||||||
|
+ maxTextWidth
|
||||||
|
+ st::whenReadPadding.right();
|
||||||
|
setMinWidth(maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WhenAction::paint(Painter &p) {
|
||||||
|
const auto loading = !isEnabled() && _content.participants.empty();
|
||||||
|
const auto selected = isSelected();
|
||||||
|
if (selected && _st.itemBgOver->c.alpha() < 255) {
|
||||||
|
p.fillRect(0, 0, width(), _height, _st.itemBg);
|
||||||
|
}
|
||||||
|
p.fillRect(0, 0, width(), _height, _st.itemBg);
|
||||||
|
const auto &icon = loading
|
||||||
|
? st::whoReadChecksDisabled
|
||||||
|
: selected
|
||||||
|
? st::whoReadChecksOver
|
||||||
|
: st::whoReadChecks;
|
||||||
|
icon.paint(p, st::whenReadIconPosition, width());
|
||||||
|
p.setPen(loading ? _st.itemFgDisabled : _st.itemFg);
|
||||||
|
_text.drawLeftElided(
|
||||||
|
p,
|
||||||
|
st::whenReadPadding.left(),
|
||||||
|
st::whenReadPadding.top(),
|
||||||
|
_textWidth,
|
||||||
|
width());
|
||||||
|
if (!_show.isEmpty()) {
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(_st.itemBgOver);
|
||||||
|
const auto radius = _showRect.height() / 2.;
|
||||||
|
p.drawRoundedRect(_showRect, radius, radius);
|
||||||
|
paintRipple(p, 0, 0);
|
||||||
|
const auto inner = _showRect.marginsRemoved(st::whenReadShowPadding);
|
||||||
|
p.setPen(_st.itemFgOver);
|
||||||
|
_show.drawLeftElided(
|
||||||
|
p,
|
||||||
|
inner.x(),
|
||||||
|
inner.y(),
|
||||||
|
inner.width(),
|
||||||
|
width());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WhenAction::refreshText() {
|
||||||
|
const auto usersCount = int(_content.participants.size());
|
||||||
|
const auto onlySeenCount = ranges::count(
|
||||||
|
_content.participants,
|
||||||
|
QString(),
|
||||||
|
&WhoReadParticipant::customEntityData);
|
||||||
|
const auto count = std::max(_content.fullReactionsCount, usersCount);
|
||||||
|
_text.setMarkedText(
|
||||||
|
st::whenReadStyle,
|
||||||
|
{ ((_content.state == WhoReadState::Unknown)
|
||||||
|
? tr::lng_context_seen_loading(tr::now)
|
||||||
|
: _content.participants.empty()
|
||||||
|
? tr::lng_context_read_hidden(tr::now)
|
||||||
|
: _content.participants.front().date) },
|
||||||
|
MenuTextOptions);
|
||||||
|
if (_content.state == WhoReadState::MyHidden) {
|
||||||
|
_show.setMarkedText(
|
||||||
|
st::whenReadStyle,
|
||||||
|
{ tr::lng_context_read_show(tr::now) },
|
||||||
|
MenuTextOptions);
|
||||||
|
} else {
|
||||||
|
_show = Text::String();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WhenAction::resizeEvent(QResizeEvent *e) {
|
||||||
|
ItemBase::resizeEvent(e);
|
||||||
|
refreshDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WhenAction::refreshDimensions() {
|
||||||
|
if (!minWidth()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto textWidth = _text.maxWidth();
|
||||||
|
const auto showWidth = _show.isEmpty() ? 0 : _show.maxWidth();
|
||||||
|
const auto &padding = st::whenReadPadding;
|
||||||
|
|
||||||
|
const auto goodWidth = padding.left()
|
||||||
|
+ textWidth
|
||||||
|
+ (showWidth
|
||||||
|
? (st::whenReadSkip
|
||||||
|
+ st::whenReadShowPadding.left()
|
||||||
|
+ showWidth
|
||||||
|
+ st::whenReadShowPadding.right())
|
||||||
|
: 0)
|
||||||
|
+ padding.right();
|
||||||
|
|
||||||
|
const auto w = std::clamp(
|
||||||
|
goodWidth,
|
||||||
|
_st.widthMin,
|
||||||
|
std::max(width(), _st.widthMin));
|
||||||
|
_textWidth = std::min(w - (goodWidth - textWidth), textWidth);
|
||||||
|
if (showWidth) {
|
||||||
|
_showRect = QRect(
|
||||||
|
padding.left() + _textWidth + st::whenReadSkip,
|
||||||
|
padding.top() - st::whenReadShowPadding.top(),
|
||||||
|
(st::whenReadShowPadding.left()
|
||||||
|
+ showWidth
|
||||||
|
+ st::whenReadShowPadding.right()),
|
||||||
|
(st::whenReadShowPadding.top()
|
||||||
|
+ st::whenReadStyle.font->height
|
||||||
|
+ st::whenReadShowPadding.bottom()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WhenAction::isEnabled() const {
|
||||||
|
return (_content.state == WhoReadState::MyHidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<QAction*> WhenAction::action() const {
|
||||||
|
return _dummyAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint WhenAction::prepareRippleStartPosition() const {
|
||||||
|
const auto result = mapFromGlobal(QCursor::pos());
|
||||||
|
return _showRect.contains(result)
|
||||||
|
? result
|
||||||
|
: Ui::RippleButton::DisabledRippleStartPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage WhenAction::prepareRippleMask() const {
|
||||||
|
return Ui::RippleAnimation::MaskByDrawer(size(), false, [&](QPainter &p) {
|
||||||
|
const auto radius = _showRect.height() / 2.;
|
||||||
|
p.drawRoundedRect(_showRect, radius, radius);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int WhenAction::contentHeight() const {
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WhoReactedEntryAction::WhoReactedEntryAction(
|
WhoReactedEntryAction::WhoReactedEntryAction(
|
||||||
|
@ -676,6 +927,16 @@ base::unique_qptr<Menu::ItemBase> WhoReactedContextAction(
|
||||||
std::move(showAllChosen));
|
std::move(showAllChosen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base::unique_qptr<Menu::ItemBase> WhenReadContextAction(
|
||||||
|
not_null<PopupMenu*> menu,
|
||||||
|
rpl::producer<WhoReadContent> content,
|
||||||
|
Fn<void()> showOrPremium) {
|
||||||
|
return base::make_unique_q<WhenAction>(
|
||||||
|
menu,
|
||||||
|
std::move(content),
|
||||||
|
std::move(showOrPremium));
|
||||||
|
}
|
||||||
|
|
||||||
WhoReactedListMenu::WhoReactedListMenu(
|
WhoReactedListMenu::WhoReactedListMenu(
|
||||||
CustomEmojiFactory factory,
|
CustomEmojiFactory factory,
|
||||||
Fn<void(uint64)> participantChosen,
|
Fn<void(uint64)> participantChosen,
|
||||||
|
|
|
@ -62,6 +62,11 @@ struct WhoReadContent {
|
||||||
Fn<void(uint64)> participantChosen,
|
Fn<void(uint64)> participantChosen,
|
||||||
Fn<void()> showAllChosen);
|
Fn<void()> showAllChosen);
|
||||||
|
|
||||||
|
[[nodiscard]] base::unique_qptr<Menu::ItemBase> WhenReadContextAction(
|
||||||
|
not_null<PopupMenu*> menu,
|
||||||
|
rpl::producer<WhoReadContent> content,
|
||||||
|
Fn<void()> showOrPremium);
|
||||||
|
|
||||||
enum class WhoReactedType : uchar {
|
enum class WhoReactedType : uchar {
|
||||||
Viewed,
|
Viewed,
|
||||||
Reacted,
|
Reacted,
|
||||||
|
|
|
@ -235,6 +235,8 @@ PRIVATE
|
||||||
ui/boxes/rate_call_box.h
|
ui/boxes/rate_call_box.h
|
||||||
ui/boxes/report_box.cpp
|
ui/boxes/report_box.cpp
|
||||||
ui/boxes/report_box.h
|
ui/boxes/report_box.h
|
||||||
|
ui/boxes/show_or_premium_box.cpp
|
||||||
|
ui/boxes/show_or_premium_box.h
|
||||||
ui/boxes/single_choice_box.cpp
|
ui/boxes/single_choice_box.cpp
|
||||||
ui/boxes/single_choice_box.h
|
ui/boxes/single_choice_box.h
|
||||||
ui/boxes/time_picker_box.cpp
|
ui/boxes/time_picker_box.cpp
|
||||||
|
|
Loading…
Add table
Reference in a new issue