mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Allow reporting / banning from reactions in groups.
This commit is contained in:
parent
c06699e8e7
commit
5401d00548
12 changed files with 241 additions and 44 deletions
|
@ -1505,6 +1505,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_report_messages_none" = "Select Messages";
|
"lng_report_messages_none" = "Select Messages";
|
||||||
"lng_report_messages_count#one" = "Report {count} Message";
|
"lng_report_messages_count#one" = "Report {count} Message";
|
||||||
"lng_report_messages_count#other" = "Report {count} Messages";
|
"lng_report_messages_count#other" = "Report {count} Messages";
|
||||||
|
"lng_report_reaction" = "Report reaction";
|
||||||
|
"lng_report_and_ban" = "Ban and report";
|
||||||
|
"lng_report_reaction_title" = "Report reaction";
|
||||||
|
"lng_report_reaction_about" = "Are you sure you want to report reactions from this user?";
|
||||||
|
"lng_report_and_ban_button" = "Ban user";
|
||||||
"lng_report_details_about" = "Please enter any additional details relevant to your report.";
|
"lng_report_details_about" = "Please enter any additional details relevant to your report.";
|
||||||
"lng_report_details" = "Additional Details";
|
"lng_report_details" = "Additional Details";
|
||||||
"lng_report_reason_spam" = "Spam";
|
"lng_report_reason_spam" = "Spam";
|
||||||
|
|
|
@ -331,7 +331,7 @@ void FieldAutocomplete::showFiltered(
|
||||||
plainQuery = base::StringViewMid(query, 1);
|
plainQuery = base::StringViewMid(query, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bool resetScroll = (_type != type || _filter != plainQuery);
|
const auto resetScroll = (_type != type || _filter != plainQuery);
|
||||||
if (resetScroll) {
|
if (resetScroll) {
|
||||||
_type = type;
|
_type = type;
|
||||||
_filter = TextUtilities::RemoveAccents(plainQuery.toString());
|
_filter = TextUtilities::RemoveAccents(plainQuery.toString());
|
||||||
|
@ -342,10 +342,11 @@ void FieldAutocomplete::showFiltered(
|
||||||
}
|
}
|
||||||
|
|
||||||
void FieldAutocomplete::showStickers(EmojiPtr emoji) {
|
void FieldAutocomplete::showStickers(EmojiPtr emoji) {
|
||||||
bool resetScroll = (_emoji != emoji);
|
const auto resetScroll = (_emoji != emoji);
|
||||||
|
if (resetScroll || emoji) {
|
||||||
_emoji = emoji;
|
_emoji = emoji;
|
||||||
_type = Type::Stickers;
|
_type = Type::Stickers;
|
||||||
if (!emoji) {
|
} else if (!emoji) {
|
||||||
rowsUpdated(
|
rowsUpdated(
|
||||||
base::take(_mrows),
|
base::take(_mrows),
|
||||||
base::take(_hrows),
|
base::take(_hrows),
|
||||||
|
|
|
@ -26,6 +26,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/media/history_view_media.h"
|
#include "history/view/media/history_view_media.h"
|
||||||
#include "history/view/media/history_view_web_page.h"
|
#include "history/view/media/history_view_web_page.h"
|
||||||
#include "history/view/reactions/history_view_reactions_list.h"
|
#include "history/view/reactions/history_view_reactions_list.h"
|
||||||
|
#include "info/info_memento.h"
|
||||||
|
#include "info/profile/info_profile_widget.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "ui/widgets/menu/menu_action.h"
|
#include "ui/widgets/menu/menu_action.h"
|
||||||
#include "ui/widgets/menu/menu_common.h"
|
#include "ui/widgets/menu/menu_common.h"
|
||||||
|
@ -1089,6 +1091,28 @@ void EditTagBox(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowWhoReadInfo(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
FullMsgId itemId,
|
||||||
|
Ui::WhoReadParticipant who) {
|
||||||
|
const auto peer = controller->session().data().peer(itemId.peer);
|
||||||
|
const auto participant = peer->owner().peer(PeerId(who.id));
|
||||||
|
const auto migrated = participant->migrateFrom();
|
||||||
|
const auto origin = who.dateReacted
|
||||||
|
? Info::Profile::Origin{
|
||||||
|
Info::Profile::GroupReactionOrigin{ peer, itemId.msg },
|
||||||
|
}
|
||||||
|
: Info::Profile::Origin();
|
||||||
|
auto memento = std::make_shared<Info::Memento>(
|
||||||
|
std::vector<std::shared_ptr<Info::ContentMemento>>{
|
||||||
|
std::make_shared<Info::Profile::Memento>(
|
||||||
|
participant,
|
||||||
|
migrated ? migrated->id : PeerId(),
|
||||||
|
origin),
|
||||||
|
});
|
||||||
|
controller->showSection(std::move(memento));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ContextMenuRequest::ContextMenuRequest(
|
ContextMenuRequest::ContextMenuRequest(
|
||||||
|
@ -1392,11 +1416,12 @@ void AddWhoReactedAction(
|
||||||
});
|
});
|
||||||
controller->show(std::move(box));
|
controller->show(std::move(box));
|
||||||
};
|
};
|
||||||
const auto participantChosen = [=](uint64 id) {
|
const auto itemId = item->fullId();
|
||||||
|
const auto participantChosen = [=](Ui::WhoReadParticipant who) {
|
||||||
if (const auto strong = weak.data()) {
|
if (const auto strong = weak.data()) {
|
||||||
strong->hideMenu();
|
strong->hideMenu();
|
||||||
}
|
}
|
||||||
controller->showPeerInfo(PeerId(id));
|
ShowWhoReadInfo(controller, itemId, who);
|
||||||
};
|
};
|
||||||
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 :(
|
||||||
|
@ -1508,8 +1533,9 @@ void ShowWhoReactedMenu(
|
||||||
struct State {
|
struct State {
|
||||||
int addedToBottom = 0;
|
int addedToBottom = 0;
|
||||||
};
|
};
|
||||||
const auto participantChosen = [=](uint64 id) {
|
const auto itemId = item->fullId();
|
||||||
controller->showPeerInfo(PeerId(id));
|
const auto participantChosen = [=](Ui::WhoReadParticipant who) {
|
||||||
|
ShowWhoReadInfo(controller, itemId, who);
|
||||||
};
|
};
|
||||||
const auto showAllChosen = [=, itemId = item->fullId()]{
|
const auto showAllChosen = [=, itemId = item->fullId()]{
|
||||||
if (const auto item = controller->session().data().message(itemId)) {
|
if (const auto item = controller->session().data().message(itemId)) {
|
||||||
|
|
|
@ -478,6 +478,10 @@ infoMainButton: SettingsButton(infoProfileButton) {
|
||||||
textFgOver: lightButtonFgOver;
|
textFgOver: lightButtonFgOver;
|
||||||
style: semiboldTextStyle;
|
style: semiboldTextStyle;
|
||||||
}
|
}
|
||||||
|
infoMainButtonAttention: SettingsButton(infoMainButton) {
|
||||||
|
textFg: attentionButtonFg;
|
||||||
|
textFgOver: attentionButtonFgOver;
|
||||||
|
}
|
||||||
infoSharedMediaButton: infoProfileButton;
|
infoSharedMediaButton: infoProfileButton;
|
||||||
infoSharedMediaBottomSkip: 12px;
|
infoSharedMediaBottomSkip: 12px;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "info/profile/info_profile_actions.h"
|
#include "info/profile/info_profile_actions.h"
|
||||||
|
|
||||||
|
#include "api/api_chat_participants.h"
|
||||||
#include "base/options.h"
|
#include "base/options.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
@ -14,12 +15,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_forum_topic.h"
|
#include "data/data_forum_topic.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
|
#include "data/data_chat.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/notify/data_notify_settings.h"
|
#include "data/notify/data_notify_settings.h"
|
||||||
#include "ui/vertical_list.h"
|
#include "ui/vertical_list.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
#include "ui/wrap/padding_wrap.h"
|
#include "ui/wrap/padding_wrap.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
#include "ui/widgets/checkbox.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
@ -44,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "info/profile/info_profile_phone_menu.h"
|
#include "info/profile/info_profile_phone_menu.h"
|
||||||
#include "info/profile/info_profile_values.h"
|
#include "info/profile/info_profile_values.h"
|
||||||
#include "info/profile/info_profile_text.h"
|
#include "info/profile/info_profile_text.h"
|
||||||
|
#include "info/profile/info_profile_widget.h"
|
||||||
#include "support/support_helper.h"
|
#include "support/support_helper.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "window/window_controller.h" // Window::Controller::show.
|
#include "window/window_controller.h" // Window::Controller::show.
|
||||||
|
@ -56,6 +60,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "api/api_blocked_peers.h"
|
#include "api/api_blocked_peers.h"
|
||||||
#include "styles/style_info.h"
|
#include "styles/style_info.h"
|
||||||
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_menu_icons.h"
|
#include "styles/style_menu_icons.h"
|
||||||
|
|
||||||
|
@ -190,14 +195,15 @@ template <typename Text, typename ToggleOn, typename Callback>
|
||||||
Text &&text,
|
Text &&text,
|
||||||
ToggleOn &&toggleOn,
|
ToggleOn &&toggleOn,
|
||||||
Callback &&callback,
|
Callback &&callback,
|
||||||
Ui::MultiSlideTracker &tracker) {
|
Ui::MultiSlideTracker &tracker,
|
||||||
|
const style::SettingsButton &st = st::infoMainButton) {
|
||||||
tracker.track(AddActionButton(
|
tracker.track(AddActionButton(
|
||||||
parent,
|
parent,
|
||||||
std::move(text) | Ui::Text::ToUpper(),
|
std::move(text) | Ui::Text::ToUpper(),
|
||||||
std::move(toggleOn),
|
std::move(toggleOn),
|
||||||
std::move(callback),
|
std::move(callback),
|
||||||
nullptr,
|
nullptr,
|
||||||
st::infoMainButton));
|
st));
|
||||||
}
|
}
|
||||||
|
|
||||||
class DetailsFiller {
|
class DetailsFiller {
|
||||||
|
@ -205,7 +211,8 @@ public:
|
||||||
DetailsFiller(
|
DetailsFiller(
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer,
|
||||||
|
Origin origin);
|
||||||
DetailsFiller(
|
DetailsFiller(
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
@ -223,6 +230,12 @@ private:
|
||||||
Ui::MultiSlideTracker fillChannelButtons(
|
Ui::MultiSlideTracker fillChannelButtons(
|
||||||
not_null<ChannelData*> channel);
|
not_null<ChannelData*> channel);
|
||||||
|
|
||||||
|
void addReportReaction(Ui::MultiSlideTracker &tracker);
|
||||||
|
void addReportReaction(
|
||||||
|
GroupReactionOrigin data,
|
||||||
|
bool ban,
|
||||||
|
Ui::MultiSlideTracker &tracker);
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename Widget,
|
typename Widget,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
|
@ -239,6 +252,7 @@ private:
|
||||||
not_null<Ui::RpWidget*> _parent;
|
not_null<Ui::RpWidget*> _parent;
|
||||||
not_null<PeerData*> _peer;
|
not_null<PeerData*> _peer;
|
||||||
Data::ForumTopic *_topic = nullptr;
|
Data::ForumTopic *_topic = nullptr;
|
||||||
|
Origin _origin;
|
||||||
object_ptr<Ui::VerticalLayout> _wrap;
|
object_ptr<Ui::VerticalLayout> _wrap;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -272,13 +286,65 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ReportReactionBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<PeerData*> participant,
|
||||||
|
GroupReactionOrigin data,
|
||||||
|
bool ban,
|
||||||
|
Fn<void()> sent) {
|
||||||
|
box->setTitle(tr::lng_report_reaction_title());
|
||||||
|
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||||
|
box,
|
||||||
|
tr::lng_report_reaction_about(),
|
||||||
|
st::boxLabel));
|
||||||
|
const auto check = ban
|
||||||
|
? box->addRow(
|
||||||
|
object_ptr<Ui::Checkbox>(
|
||||||
|
box,
|
||||||
|
tr::lng_report_and_ban_button(tr::now),
|
||||||
|
true),
|
||||||
|
st::boxRowPadding + QMargins{ 0, st::boxLittleSkip, 0, 0 })
|
||||||
|
: nullptr;
|
||||||
|
box->addButton(tr::lng_report_button(), [=] {
|
||||||
|
const auto chat = data.group->asChat();
|
||||||
|
const auto channel = data.group->asMegagroup();
|
||||||
|
if (check && check->checked()) {
|
||||||
|
if (chat) {
|
||||||
|
chat->session().api().chatParticipants().kick(
|
||||||
|
chat,
|
||||||
|
participant);
|
||||||
|
} else if (channel) {
|
||||||
|
channel->session().api().chatParticipants().kick(
|
||||||
|
channel,
|
||||||
|
participant,
|
||||||
|
ChatRestrictionsInfo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.group->session().api().request(MTPmessages_ReportReaction(
|
||||||
|
data.group->input,
|
||||||
|
MTP_int(data.messageId.bare),
|
||||||
|
participant->input
|
||||||
|
)).done(crl::guard(controller, [=] {
|
||||||
|
controller->showToast(tr::lng_report_thanks(tr::now));
|
||||||
|
})).send();
|
||||||
|
sent();
|
||||||
|
box->closeBox();
|
||||||
|
}, st::attentionBoxButton);
|
||||||
|
box->addButton(tr::lng_cancel(), [=] {
|
||||||
|
box->closeBox();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
DetailsFiller::DetailsFiller(
|
DetailsFiller::DetailsFiller(
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<PeerData*> peer)
|
not_null<PeerData*> peer,
|
||||||
|
Origin origin)
|
||||||
: _controller(controller)
|
: _controller(controller)
|
||||||
, _parent(parent)
|
, _parent(parent)
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
|
, _origin(origin)
|
||||||
, _wrap(_parent) {
|
, _wrap(_parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,6 +719,58 @@ void DetailsFiller::setupMainButtons() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DetailsFiller::addReportReaction(Ui::MultiSlideTracker &tracker) {
|
||||||
|
v::match(_origin.data, [&](GroupReactionOrigin data) {
|
||||||
|
const auto user = _peer->asUser();
|
||||||
|
if (_peer->isSelf()) {
|
||||||
|
return;
|
||||||
|
} else if (const auto chat = data.group->asChat()) {
|
||||||
|
const auto ban = chat->canBanMembers()
|
||||||
|
&& (!user || !chat->admins.contains(_peer))
|
||||||
|
&& (!user || chat->creator != user->id);
|
||||||
|
addReportReaction(data, ban, tracker);
|
||||||
|
} else if (const auto channel = data.group->asMegagroup()) {
|
||||||
|
const auto ban = channel->canBanMembers()
|
||||||
|
&& (!user || !channel->mgInfo->admins.contains(user->id))
|
||||||
|
&& (!user || channel->mgInfo->creator != user);
|
||||||
|
addReportReaction(data, ban, tracker);
|
||||||
|
}
|
||||||
|
}, [](const auto &) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DetailsFiller::addReportReaction(
|
||||||
|
GroupReactionOrigin data,
|
||||||
|
bool ban,
|
||||||
|
Ui::MultiSlideTracker &tracker) {
|
||||||
|
const auto peer = _peer;
|
||||||
|
if (!peer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto controller = _controller->parentController();
|
||||||
|
const auto forceHidden = std::make_shared<rpl::variable<bool>>(false);
|
||||||
|
const auto user = peer->asUser();
|
||||||
|
auto shown = user
|
||||||
|
? rpl::combine(
|
||||||
|
Info::Profile::IsContactValue(user),
|
||||||
|
forceHidden->value(),
|
||||||
|
!rpl::mappers::_1 && !rpl::mappers::_2
|
||||||
|
) | rpl::type_erased()
|
||||||
|
: (forceHidden->value() | rpl::map(!rpl::mappers::_1));
|
||||||
|
const auto sent = [=] {
|
||||||
|
*forceHidden = true;
|
||||||
|
};
|
||||||
|
AddMainButton(
|
||||||
|
_wrap,
|
||||||
|
(ban
|
||||||
|
? tr::lng_report_and_ban()
|
||||||
|
: tr::lng_report_reaction()),
|
||||||
|
std::move(shown),
|
||||||
|
[=] { controller->show(
|
||||||
|
Box(ReportReactionBox, controller, peer, data, ban, sent)); },
|
||||||
|
tracker,
|
||||||
|
st::infoMainButtonAttention);
|
||||||
|
}
|
||||||
|
|
||||||
Ui::MultiSlideTracker DetailsFiller::fillTopicButtons() {
|
Ui::MultiSlideTracker DetailsFiller::fillTopicButtons() {
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
|
|
||||||
|
@ -719,6 +837,9 @@ Ui::MultiSlideTracker DetailsFiller::fillUserButtons(
|
||||||
} else {
|
} else {
|
||||||
addSendMessageButton();
|
addSendMessageButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addReportReaction(tracker);
|
||||||
|
|
||||||
return tracker;
|
return tracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1055,8 +1176,9 @@ const char kOptionShowPeerIdBelowAbout[] = "show-peer-id-below-about";
|
||||||
object_ptr<Ui::RpWidget> SetupDetails(
|
object_ptr<Ui::RpWidget> SetupDetails(
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer,
|
||||||
DetailsFiller filler(controller, parent, peer);
|
Origin origin) {
|
||||||
|
DetailsFiller filler(controller, parent, peer, origin);
|
||||||
return filler.fill();
|
return filler.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,13 @@ namespace Info::Profile {
|
||||||
|
|
||||||
extern const char kOptionShowPeerIdBelowAbout[];
|
extern const char kOptionShowPeerIdBelowAbout[];
|
||||||
|
|
||||||
|
struct Origin;
|
||||||
|
|
||||||
object_ptr<Ui::RpWidget> SetupDetails(
|
object_ptr<Ui::RpWidget> SetupDetails(
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer,
|
||||||
|
Origin origin);
|
||||||
|
|
||||||
object_ptr<Ui::RpWidget> SetupDetails(
|
object_ptr<Ui::RpWidget> SetupDetails(
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
|
|
|
@ -49,13 +49,14 @@ namespace Profile {
|
||||||
|
|
||||||
InnerWidget::InnerWidget(
|
InnerWidget::InnerWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Controller*> controller)
|
not_null<Controller*> controller,
|
||||||
|
Origin origin)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _controller(controller)
|
, _controller(controller)
|
||||||
, _peer(_controller->key().peer())
|
, _peer(_controller->key().peer())
|
||||||
, _migrated(_controller->migrated())
|
, _migrated(_controller->migrated())
|
||||||
, _topic(_controller->key().topic())
|
, _topic(_controller->key().topic())
|
||||||
, _content(setupContent(this)) {
|
, _content(setupContent(this, origin)) {
|
||||||
_content->heightValue(
|
_content->heightValue(
|
||||||
) | rpl::start_with_next([this](int height) {
|
) | rpl::start_with_next([this](int height) {
|
||||||
if (!_inResize) {
|
if (!_inResize) {
|
||||||
|
@ -66,7 +67,8 @@ InnerWidget::InnerWidget(
|
||||||
}
|
}
|
||||||
|
|
||||||
object_ptr<Ui::RpWidget> InnerWidget::setupContent(
|
object_ptr<Ui::RpWidget> InnerWidget::setupContent(
|
||||||
not_null<RpWidget*> parent) {
|
not_null<RpWidget*> parent,
|
||||||
|
Origin origin) {
|
||||||
auto result = object_ptr<Ui::VerticalLayout>(parent);
|
auto result = object_ptr<Ui::VerticalLayout>(parent);
|
||||||
if (const auto user = _peer->asUser()) {
|
if (const auto user = _peer->asUser()) {
|
||||||
user->session().changes().peerFlagsValue(
|
user->session().changes().peerFlagsValue(
|
||||||
|
@ -104,7 +106,7 @@ object_ptr<Ui::RpWidget> InnerWidget::setupContent(
|
||||||
}
|
}
|
||||||
result->add(SetupDetails(_controller, parent, _topic));
|
result->add(SetupDetails(_controller, parent, _topic));
|
||||||
} else {
|
} else {
|
||||||
result->add(SetupDetails(_controller, parent, _peer));
|
result->add(SetupDetails(_controller, parent, _peer, origin));
|
||||||
}
|
}
|
||||||
result->add(setupSharedMedia(result.data()));
|
result->add(setupSharedMedia(result.data()));
|
||||||
if (_topic) {
|
if (_topic) {
|
||||||
|
|
|
@ -37,12 +37,14 @@ namespace Profile {
|
||||||
class Memento;
|
class Memento;
|
||||||
class Members;
|
class Members;
|
||||||
class Cover;
|
class Cover;
|
||||||
|
struct Origin;
|
||||||
|
|
||||||
class InnerWidget final : public Ui::RpWidget {
|
class InnerWidget final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
InnerWidget(
|
InnerWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Controller*> controller);
|
not_null<Controller*> controller,
|
||||||
|
Origin origin);
|
||||||
|
|
||||||
void saveState(not_null<Memento*> memento);
|
void saveState(not_null<Memento*> memento);
|
||||||
void restoreState(not_null<Memento*> memento);
|
void restoreState(not_null<Memento*> memento);
|
||||||
|
@ -57,7 +59,9 @@ protected:
|
||||||
int visibleBottom) override;
|
int visibleBottom) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
object_ptr<RpWidget> setupContent(not_null<RpWidget*> parent);
|
object_ptr<RpWidget> setupContent(
|
||||||
|
not_null<RpWidget*> parent,
|
||||||
|
Origin origin);
|
||||||
object_ptr<RpWidget> setupSharedMedia(not_null<RpWidget*> parent);
|
object_ptr<RpWidget> setupSharedMedia(not_null<RpWidget*> parent);
|
||||||
void setupMembers(not_null<Ui::VerticalLayout*> container);
|
void setupMembers(not_null<Ui::VerticalLayout*> container);
|
||||||
|
|
||||||
|
@ -71,6 +75,8 @@ private:
|
||||||
PeerData * const _migrated = nullptr;
|
PeerData * const _migrated = nullptr;
|
||||||
Data::ForumTopic * const _topic = nullptr;
|
Data::ForumTopic * const _topic = nullptr;
|
||||||
|
|
||||||
|
PeerData *_reactionGroup = nullptr;
|
||||||
|
|
||||||
std::shared_ptr<Data::PhotoMedia> _nonPersonalView;
|
std::shared_ptr<Data::PhotoMedia> _nonPersonalView;
|
||||||
|
|
||||||
Members *_members = nullptr;
|
Members *_members = nullptr;
|
||||||
|
|
|
@ -25,18 +25,24 @@ Memento::Memento(not_null<Controller*> controller)
|
||||||
: Memento(
|
: Memento(
|
||||||
controller->peer(),
|
controller->peer(),
|
||||||
controller->topic(),
|
controller->topic(),
|
||||||
controller->migratedPeerId()) {
|
controller->migratedPeerId(),
|
||||||
|
{ v::null }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Memento::Memento(not_null<PeerData*> peer, PeerId migratedPeerId)
|
Memento::Memento(
|
||||||
: Memento(peer, nullptr, migratedPeerId) {
|
not_null<PeerData*> peer,
|
||||||
|
PeerId migratedPeerId,
|
||||||
|
Origin origin)
|
||||||
|
: Memento(peer, nullptr, migratedPeerId, origin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Memento::Memento(
|
Memento::Memento(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Data::ForumTopic *topic,
|
Data::ForumTopic *topic,
|
||||||
PeerId migratedPeerId)
|
PeerId migratedPeerId,
|
||||||
: ContentMemento(peer, topic, migratedPeerId) {
|
Origin origin)
|
||||||
|
: ContentMemento(peer, topic, migratedPeerId)
|
||||||
|
, _origin(origin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Memento::Memento(not_null<Data::ForumTopic*> topic)
|
Memento::Memento(not_null<Data::ForumTopic*> topic)
|
||||||
|
@ -51,7 +57,7 @@ object_ptr<ContentWidget> Memento::createWidget(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
not_null<Controller*> controller,
|
not_null<Controller*> controller,
|
||||||
const QRect &geometry) {
|
const QRect &geometry) {
|
||||||
auto result = object_ptr<Widget>(parent, controller);
|
auto result = object_ptr<Widget>(parent, controller, _origin);
|
||||||
result->setInternalState(geometry, this);
|
result->setInternalState(geometry, this);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -66,13 +72,17 @@ std::unique_ptr<MembersState> Memento::membersState() {
|
||||||
|
|
||||||
Memento::~Memento() = default;
|
Memento::~Memento() = default;
|
||||||
|
|
||||||
Widget::Widget(QWidget *parent, not_null<Controller*> controller)
|
Widget::Widget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Controller*> controller,
|
||||||
|
Origin origin)
|
||||||
: ContentWidget(parent, controller) {
|
: ContentWidget(parent, controller) {
|
||||||
controller->setSearchEnabledByContent(false);
|
controller->setSearchEnabledByContent(false);
|
||||||
|
|
||||||
_inner = setInnerWidget(object_ptr<InnerWidget>(
|
_inner = setInnerWidget(object_ptr<InnerWidget>(
|
||||||
this,
|
this,
|
||||||
controller));
|
controller,
|
||||||
|
origin));
|
||||||
_inner->move(0, 0);
|
_inner->move(0, 0);
|
||||||
_inner->scrollToRequests(
|
_inner->scrollToRequests(
|
||||||
) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
||||||
|
|
|
@ -18,10 +18,22 @@ namespace Info::Profile {
|
||||||
class InnerWidget;
|
class InnerWidget;
|
||||||
struct MembersState;
|
struct MembersState;
|
||||||
|
|
||||||
|
struct GroupReactionOrigin {
|
||||||
|
not_null<PeerData*> group;
|
||||||
|
MsgId messageId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Origin {
|
||||||
|
std::variant<v::null_t, GroupReactionOrigin> data;
|
||||||
|
};
|
||||||
|
|
||||||
class Memento final : public ContentMemento {
|
class Memento final : public ContentMemento {
|
||||||
public:
|
public:
|
||||||
explicit Memento(not_null<Controller*> controller);
|
explicit Memento(not_null<Controller*> controller);
|
||||||
Memento(not_null<PeerData*> peer, PeerId migratedPeerId);
|
Memento(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
PeerId migratedPeerId,
|
||||||
|
Origin origin = { v::null });
|
||||||
explicit Memento(not_null<Data::ForumTopic*> topic);
|
explicit Memento(not_null<Data::ForumTopic*> topic);
|
||||||
|
|
||||||
object_ptr<ContentWidget> createWidget(
|
object_ptr<ContentWidget> createWidget(
|
||||||
|
@ -31,6 +43,10 @@ public:
|
||||||
|
|
||||||
Section section() const override;
|
Section section() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] Origin origin() const {
|
||||||
|
return _origin;
|
||||||
|
}
|
||||||
|
|
||||||
void setMembersState(std::unique_ptr<MembersState> state);
|
void setMembersState(std::unique_ptr<MembersState> state);
|
||||||
std::unique_ptr<MembersState> membersState();
|
std::unique_ptr<MembersState> membersState();
|
||||||
|
|
||||||
|
@ -40,15 +56,17 @@ private:
|
||||||
Memento(
|
Memento(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Data::ForumTopic *topic,
|
Data::ForumTopic *topic,
|
||||||
PeerId migratedPeerId);
|
PeerId migratedPeerId,
|
||||||
|
Origin origin);
|
||||||
|
|
||||||
std::unique_ptr<MembersState> _membersState;
|
std::unique_ptr<MembersState> _membersState;
|
||||||
|
Origin _origin;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Widget final : public ContentWidget {
|
class Widget final : public ContentWidget {
|
||||||
public:
|
public:
|
||||||
Widget(QWidget *parent, not_null<Controller*> controller);
|
Widget(QWidget *parent, not_null<Controller*> controller, Origin origin);
|
||||||
|
|
||||||
bool showInternal(
|
bool showInternal(
|
||||||
not_null<ContentMemento*> memento) override;
|
not_null<ContentMemento*> memento) override;
|
||||||
|
|
|
@ -80,7 +80,7 @@ public:
|
||||||
not_null<PopupMenu*> parentMenu,
|
not_null<PopupMenu*> parentMenu,
|
||||||
rpl::producer<WhoReadContent> content,
|
rpl::producer<WhoReadContent> content,
|
||||||
CustomEmojiFactory factory,
|
CustomEmojiFactory factory,
|
||||||
Fn<void(uint64)> participantChosen,
|
Fn<void(WhoReadParticipant)> participantChosen,
|
||||||
Fn<void()> showAllChosen);
|
Fn<void()> showAllChosen);
|
||||||
|
|
||||||
bool isEnabled() const override;
|
bool isEnabled() const override;
|
||||||
|
@ -105,7 +105,7 @@ private:
|
||||||
|
|
||||||
const not_null<PopupMenu*> _parentMenu;
|
const not_null<PopupMenu*> _parentMenu;
|
||||||
const not_null<QAction*> _dummyAction;
|
const not_null<QAction*> _dummyAction;
|
||||||
const Fn<void(uint64)> _participantChosen;
|
const Fn<void(WhoReadParticipant)> _participantChosen;
|
||||||
const Fn<void()> _showAllChosen;
|
const Fn<void()> _showAllChosen;
|
||||||
const std::unique_ptr<GroupCallUserpics> _userpics;
|
const std::unique_ptr<GroupCallUserpics> _userpics;
|
||||||
const style::Menu &_st;
|
const style::Menu &_st;
|
||||||
|
@ -186,7 +186,7 @@ Action::Action(
|
||||||
not_null<PopupMenu*> parentMenu,
|
not_null<PopupMenu*> parentMenu,
|
||||||
rpl::producer<WhoReadContent> content,
|
rpl::producer<WhoReadContent> content,
|
||||||
Text::CustomEmojiFactory factory,
|
Text::CustomEmojiFactory factory,
|
||||||
Fn<void(uint64)> participantChosen,
|
Fn<void(WhoReadParticipant)> participantChosen,
|
||||||
Fn<void()> showAllChosen)
|
Fn<void()> showAllChosen)
|
||||||
: ItemBase(parentMenu->menu(), parentMenu->menu()->st())
|
: ItemBase(parentMenu->menu(), parentMenu->menu()->st())
|
||||||
, _parentMenu(parentMenu)
|
, _parentMenu(parentMenu)
|
||||||
|
@ -252,7 +252,7 @@ Action::Action(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
if (_content.participants.size() == 1) {
|
if (_content.participants.size() == 1) {
|
||||||
if (const auto onstack = _participantChosen) {
|
if (const auto onstack = _participantChosen) {
|
||||||
onstack(_content.participants.front().id);
|
onstack(_content.participants.front());
|
||||||
}
|
}
|
||||||
} else if (_content.fullReactionsCount > 0) {
|
} else if (_content.fullReactionsCount > 0) {
|
||||||
if (const auto onstack = _showAllChosen) {
|
if (const auto onstack = _showAllChosen) {
|
||||||
|
@ -909,7 +909,7 @@ base::unique_qptr<Menu::ItemBase> WhoReactedContextAction(
|
||||||
not_null<PopupMenu*> menu,
|
not_null<PopupMenu*> menu,
|
||||||
rpl::producer<WhoReadContent> content,
|
rpl::producer<WhoReadContent> content,
|
||||||
CustomEmojiFactory factory,
|
CustomEmojiFactory factory,
|
||||||
Fn<void(uint64)> participantChosen,
|
Fn<void(WhoReadParticipant)> participantChosen,
|
||||||
Fn<void()> showAllChosen) {
|
Fn<void()> showAllChosen) {
|
||||||
return base::make_unique_q<Action>(
|
return base::make_unique_q<Action>(
|
||||||
menu,
|
menu,
|
||||||
|
@ -931,7 +931,7 @@ base::unique_qptr<Menu::ItemBase> WhenReadContextAction(
|
||||||
|
|
||||||
WhoReactedListMenu::WhoReactedListMenu(
|
WhoReactedListMenu::WhoReactedListMenu(
|
||||||
CustomEmojiFactory factory,
|
CustomEmojiFactory factory,
|
||||||
Fn<void(uint64)> participantChosen,
|
Fn<void(WhoReadParticipant)> participantChosen,
|
||||||
Fn<void()> showAllChosen)
|
Fn<void()> showAllChosen)
|
||||||
: _customEmojiFactory(std::move(factory))
|
: _customEmojiFactory(std::move(factory))
|
||||||
, _participantChosen(std::move(participantChosen))
|
, _participantChosen(std::move(participantChosen))
|
||||||
|
@ -983,8 +983,8 @@ void WhoReactedListMenu::populate(
|
||||||
++index;
|
++index;
|
||||||
};
|
};
|
||||||
for (const auto &participant : content.participants) {
|
for (const auto &participant : content.participants) {
|
||||||
const auto chosen = [call = _participantChosen, id = participant.id]{
|
const auto chosen = [call = _participantChosen, participant] {
|
||||||
call(id);
|
call(participant);
|
||||||
};
|
};
|
||||||
append({
|
append({
|
||||||
.text = participant.name,
|
.text = participant.name,
|
||||||
|
|
|
@ -59,7 +59,7 @@ struct WhoReadContent {
|
||||||
not_null<PopupMenu*> menu,
|
not_null<PopupMenu*> menu,
|
||||||
rpl::producer<WhoReadContent> content,
|
rpl::producer<WhoReadContent> content,
|
||||||
Text::CustomEmojiFactory factory,
|
Text::CustomEmojiFactory factory,
|
||||||
Fn<void(uint64)> participantChosen,
|
Fn<void(WhoReadParticipant)> participantChosen,
|
||||||
Fn<void()> showAllChosen);
|
Fn<void()> showAllChosen);
|
||||||
|
|
||||||
[[nodiscard]] base::unique_qptr<Menu::ItemBase> WhenReadContextAction(
|
[[nodiscard]] base::unique_qptr<Menu::ItemBase> WhenReadContextAction(
|
||||||
|
@ -123,7 +123,7 @@ class WhoReactedListMenu final {
|
||||||
public:
|
public:
|
||||||
WhoReactedListMenu(
|
WhoReactedListMenu(
|
||||||
Text::CustomEmojiFactory factory,
|
Text::CustomEmojiFactory factory,
|
||||||
Fn<void(uint64)> participantChosen,
|
Fn<void(WhoReadParticipant)> participantChosen,
|
||||||
Fn<void()> showAllChosen);
|
Fn<void()> showAllChosen);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
@ -136,7 +136,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Text::CustomEmojiFactory _customEmojiFactory;
|
const Text::CustomEmojiFactory _customEmojiFactory;
|
||||||
const Fn<void(uint64)> _participantChosen;
|
const Fn<void(WhoReadParticipant)> _participantChosen;
|
||||||
const Fn<void()> _showAllChosen;
|
const Fn<void()> _showAllChosen;
|
||||||
|
|
||||||
std::vector<not_null<WhoReactedEntryAction*>> _actions;
|
std::vector<not_null<WhoReactedEntryAction*>> _actions;
|
||||||
|
|
Loading…
Add table
Reference in a new issue