mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Implement a special context menu for sender userpic.
This commit is contained in:
parent
93c01e5f1e
commit
5f037462ed
14 changed files with 137 additions and 16 deletions
|
@ -3623,6 +3623,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_context_make_paid" = "Make This Content Paid";
|
"lng_context_make_paid" = "Make This Content Paid";
|
||||||
"lng_context_change_price" = "Change Price";
|
"lng_context_change_price" = "Change Price";
|
||||||
|
|
||||||
|
"lng_context_mention" = "Mention";
|
||||||
|
"lng_context_search_from" = "Search messages";
|
||||||
|
|
||||||
"lng_factcheck_title" = "Fact Check";
|
"lng_factcheck_title" = "Fact Check";
|
||||||
"lng_factcheck_placeholder" = "Add Facts or Context";
|
"lng_factcheck_placeholder" = "Add Facts or Context";
|
||||||
"lng_factcheck_whats_this" = "what's this?";
|
"lng_factcheck_whats_this" = "what's this?";
|
||||||
|
|
|
@ -2204,6 +2204,9 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
const auto linkPhoneNumber = link
|
const auto linkPhoneNumber = link
|
||||||
? link->property(kPhoneNumberLinkProperty).toString()
|
? link->property(kPhoneNumberLinkProperty).toString()
|
||||||
: QString();
|
: QString();
|
||||||
|
const auto linkUserpicPeerId = (link && _dragStateUserpic)
|
||||||
|
? link->property(kPeerLinkPeerIdProperty).toULongLong()
|
||||||
|
: 0;
|
||||||
const auto session = &this->session();
|
const auto session = &this->session();
|
||||||
_whoReactedMenuLifetime.destroy();
|
_whoReactedMenuLifetime.destroy();
|
||||||
if (!clickedReaction.empty()
|
if (!clickedReaction.empty()
|
||||||
|
@ -2227,6 +2230,14 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_menu = base::make_unique_q<Ui::PopupMenu>(this, st::popupMenuWithIcons);
|
_menu = base::make_unique_q<Ui::PopupMenu>(this, st::popupMenuWithIcons);
|
||||||
|
if (linkUserpicPeerId) {
|
||||||
|
_widget->fillSenderUserpicMenu(
|
||||||
|
_menu.get(),
|
||||||
|
session->data().peer(PeerId(linkUserpicPeerId)));
|
||||||
|
_menu->popup(e->globalPos());
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto controller = _controller;
|
const auto controller = _controller;
|
||||||
const auto addItemActions = [&](
|
const auto addItemActions = [&](
|
||||||
HistoryItem *item,
|
HistoryItem *item,
|
||||||
|
@ -3938,6 +3949,7 @@ void HistoryInner::mouseActionUpdate() {
|
||||||
|
|
||||||
TextState dragState;
|
TextState dragState;
|
||||||
ClickHandlerHost *lnkhost = nullptr;
|
ClickHandlerHost *lnkhost = nullptr;
|
||||||
|
auto dragStateUserpic = false;
|
||||||
auto selectingText = (item == _mouseActionItem)
|
auto selectingText = (item == _mouseActionItem)
|
||||||
&& (view == Element::Hovered())
|
&& (view == Element::Hovered())
|
||||||
&& !_selected.empty()
|
&& !_selected.empty()
|
||||||
|
@ -4033,6 +4045,7 @@ void HistoryInner::mouseActionUpdate() {
|
||||||
// stop enumeration if we've found a userpic under the cursor
|
// stop enumeration if we've found a userpic under the cursor
|
||||||
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
|
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
|
||||||
dragState = TextState(nullptr, view->fromPhotoLink());
|
dragState = TextState(nullptr, view->fromPhotoLink());
|
||||||
|
dragStateUserpic = true;
|
||||||
_dragStateItem = nullptr;
|
_dragStateItem = nullptr;
|
||||||
lnkhost = view;
|
lnkhost = view;
|
||||||
return false;
|
return false;
|
||||||
|
@ -4044,6 +4057,7 @@ void HistoryInner::mouseActionUpdate() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto lnkChanged = ClickHandler::setActive(dragState.link, lnkhost);
|
auto lnkChanged = ClickHandler::setActive(dragState.link, lnkhost);
|
||||||
|
_dragStateUserpic = dragStateUserpic;
|
||||||
if (lnkChanged || dragState.cursor != _mouseCursorState) {
|
if (lnkChanged || dragState.cursor != _mouseCursorState) {
|
||||||
Ui::Tooltip::Hide();
|
Ui::Tooltip::Hide();
|
||||||
}
|
}
|
||||||
|
|
|
@ -499,6 +499,7 @@ private:
|
||||||
HistoryItem *_dragStateItem = nullptr;
|
HistoryItem *_dragStateItem = nullptr;
|
||||||
CursorState _mouseCursorState = CursorState();
|
CursorState _mouseCursorState = CursorState();
|
||||||
uint16 _mouseTextSymbol = 0;
|
uint16 _mouseTextSymbol = 0;
|
||||||
|
bool _dragStateUserpic = false;
|
||||||
bool _pressWasInactive = false;
|
bool _pressWasInactive = false;
|
||||||
bool _recountedAfterPendingResizedItems = false;
|
bool _recountedAfterPendingResizedItems = false;
|
||||||
bool _useCornerReaction = false;
|
bool _useCornerReaction = false;
|
||||||
|
|
|
@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/emoji_config.h"
|
#include "ui/emoji_config.h"
|
||||||
#include "ui/chat/attach/attach_prepare.h"
|
#include "ui/chat/attach/attach_prepare.h"
|
||||||
#include "ui/chat/choose_theme_controller.h"
|
#include "ui/chat/choose_theme_controller.h"
|
||||||
|
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/inner_dropdown.h"
|
#include "ui/widgets/inner_dropdown.h"
|
||||||
#include "ui/widgets/dropdown_menu.h"
|
#include "ui/widgets/dropdown_menu.h"
|
||||||
|
@ -5115,7 +5116,10 @@ bool HistoryWidget::updateCmdStartShown() {
|
||||||
return commandsChanged || buttonChanged || textChanged;
|
return commandsChanged || buttonChanged || textChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::searchInChatEmbedded(Dialogs::Key chat, QString query) {
|
bool HistoryWidget::searchInChatEmbedded(
|
||||||
|
QString query,
|
||||||
|
Dialogs::Key chat,
|
||||||
|
PeerData *searchFrom) {
|
||||||
const auto peer = chat.peer(); // windows todo
|
const auto peer = chat.peer(); // windows todo
|
||||||
if (!peer || Window::SeparateId(peer) != controller()->windowId()) {
|
if (!peer || Window::SeparateId(peer) != controller()->windowId()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -8071,6 +8075,18 @@ void HistoryWidget::editMessage(
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::fillSenderUserpicMenu(
|
||||||
|
not_null<Ui::PopupMenu*> menu,
|
||||||
|
not_null<PeerData*> peer) {
|
||||||
|
const auto inGroup = _peer && (_peer->isChat() || _peer->isMegagroup());
|
||||||
|
Window::FillSenderUserpicMenu(
|
||||||
|
controller(),
|
||||||
|
peer,
|
||||||
|
(inGroup && _canSendTexts) ? _field.data() : nullptr,
|
||||||
|
inGroup ? _peer->owner().history(_peer) : Dialogs::Key(),
|
||||||
|
Ui::Menu::CreateAddActionCallback(menu));
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::hidePinnedMessage() {
|
void HistoryWidget::hidePinnedMessage() {
|
||||||
Expects(_pinnedBar != nullptr);
|
Expects(_pinnedBar != nullptr);
|
||||||
|
|
||||||
|
|
|
@ -211,6 +211,10 @@ public:
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
const TextSelection &selection);
|
const TextSelection &selection);
|
||||||
|
|
||||||
|
void fillSenderUserpicMenu(
|
||||||
|
not_null<Ui::PopupMenu*> menu,
|
||||||
|
not_null<PeerData*> peer);
|
||||||
|
|
||||||
[[nodiscard]] FullReplyTo replyTo() const;
|
[[nodiscard]] FullReplyTo replyTo() const;
|
||||||
bool lastForceReplyReplied(const FullMsgId &replyTo) const;
|
bool lastForceReplyReplied(const FullMsgId &replyTo) const;
|
||||||
bool lastForceReplyReplied() const;
|
bool lastForceReplyReplied() const;
|
||||||
|
@ -263,7 +267,10 @@ public:
|
||||||
[[nodiscard]] rpl::producer<> cancelRequests() const {
|
[[nodiscard]] rpl::producer<> cancelRequests() const {
|
||||||
return _cancelRequests.events();
|
return _cancelRequests.events();
|
||||||
}
|
}
|
||||||
bool searchInChatEmbedded(Dialogs::Key chat, QString query);
|
bool searchInChatEmbedded(
|
||||||
|
QString query,
|
||||||
|
Dialogs::Key chat,
|
||||||
|
PeerData *searchFrom = nullptr);
|
||||||
|
|
||||||
void updateNotifyControls();
|
void updateNotifyControls();
|
||||||
|
|
||||||
|
|
|
@ -329,7 +329,10 @@ void SublistWidget::setInternalState(
|
||||||
restoreState(memento);
|
restoreState(memento);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SublistWidget::searchInChatEmbedded(Dialogs::Key chat, QString query) {
|
bool SublistWidget::searchInChatEmbedded(
|
||||||
|
QString query,
|
||||||
|
Dialogs::Key chat,
|
||||||
|
PeerData *searchFrom) {
|
||||||
const auto sublist = chat.sublist();
|
const auto sublist = chat.sublist();
|
||||||
if (!sublist || sublist != _sublist) {
|
if (!sublist || sublist != _sublist) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -76,7 +76,10 @@ public:
|
||||||
return Window::SectionActionResult::Fallback;
|
return Window::SectionActionResult::Fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool searchInChatEmbedded(Dialogs::Key chat, QString query) override;
|
bool searchInChatEmbedded(
|
||||||
|
QString query,
|
||||||
|
Dialogs::Key chat,
|
||||||
|
PeerData *searchFrom = nullptr) override;
|
||||||
|
|
||||||
// Float player interface.
|
// Float player interface.
|
||||||
bool floatPlayerHandleWheelEvent(QEvent *e) override;
|
bool floatPlayerHandleWheelEvent(QEvent *e) override;
|
||||||
|
|
|
@ -744,7 +744,10 @@ void MainWidget::hideSingleUseKeyboard(FullMsgId replyToId) {
|
||||||
_history->hideSingleUseKeyboard(replyToId);
|
_history->hideSingleUseKeyboard(replyToId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::searchMessages(const QString &query, Dialogs::Key inChat) {
|
void MainWidget::searchMessages(
|
||||||
|
const QString &query,
|
||||||
|
Dialogs::Key inChat,
|
||||||
|
PeerData *searchFrom) {
|
||||||
const auto complex = Data::HashtagWithUsernameFromQuery(query);
|
const auto complex = Data::HashtagWithUsernameFromQuery(query);
|
||||||
if (!complex.username.isEmpty()) {
|
if (!complex.username.isEmpty()) {
|
||||||
_controller->showPeerByLink(Window::PeerByLinkInfo{
|
_controller->showPeerByLink(Window::PeerByLinkInfo{
|
||||||
|
@ -760,6 +763,7 @@ void MainWidget::searchMessages(const QString &query, Dialogs::Key inChat) {
|
||||||
.inChat = ((tags.empty() || inChat.sublist())
|
.inChat = ((tags.empty() || inChat.sublist())
|
||||||
? inChat
|
? inChat
|
||||||
: session().data().history(session().user())),
|
: session().data().history(session().user())),
|
||||||
|
.fromPeer = inChat ? searchFrom : nullptr,
|
||||||
.tags = tags,
|
.tags = tags,
|
||||||
.query = tags.empty() ? query : QString(),
|
.query = tags.empty() ? query : QString(),
|
||||||
};
|
};
|
||||||
|
@ -779,12 +783,15 @@ void MainWidget::searchMessages(const QString &query, Dialogs::Key inChat) {
|
||||||
controller()->session().user());
|
controller()->session().user());
|
||||||
}
|
}
|
||||||
if ((!_mainSection
|
if ((!_mainSection
|
||||||
|| !_mainSection->searchInChatEmbedded(inChat, query))
|
|| !_mainSection->searchInChatEmbedded(query, inChat, searchFrom))
|
||||||
&& !_history->searchInChatEmbedded(inChat, query)) {
|
&& !_history->searchInChatEmbedded(query, inChat, searchFrom)) {
|
||||||
const auto account = not_null(&session().account());
|
const auto account = not_null(&session().account());
|
||||||
if (const auto window = Core::App().windowFor(account)) {
|
if (const auto window = Core::App().windowFor(account)) {
|
||||||
if (const auto controller = window->sessionController()) {
|
if (const auto controller = window->sessionController()) {
|
||||||
controller->content()->searchMessages(query, inChat);
|
controller->content()->searchMessages(
|
||||||
|
query,
|
||||||
|
inChat,
|
||||||
|
searchFrom);
|
||||||
controller->widget()->activate();
|
controller->widget()->activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,10 @@ public:
|
||||||
void sendBotCommand(Bot::SendCommandRequest request);
|
void sendBotCommand(Bot::SendCommandRequest request);
|
||||||
void hideSingleUseKeyboard(FullMsgId replyToId);
|
void hideSingleUseKeyboard(FullMsgId replyToId);
|
||||||
|
|
||||||
void searchMessages(const QString &query, Dialogs::Key inChat);
|
void searchMessages(
|
||||||
|
const QString &query,
|
||||||
|
Dialogs::Key inChat,
|
||||||
|
PeerData *searchFrom = nullptr);
|
||||||
|
|
||||||
void setChatBackground(
|
void setChatBackground(
|
||||||
const Data::WallPaper &background,
|
const Data::WallPaper &background,
|
||||||
|
|
|
@ -148,7 +148,10 @@ public:
|
||||||
MsgId messageId) {
|
MsgId messageId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool searchInChatEmbedded(Dialogs::Key chat, QString query) {
|
virtual bool searchInChatEmbedded(
|
||||||
|
QString query,
|
||||||
|
Dialogs::Key chat,
|
||||||
|
PeerData *searchFrom = nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2727,6 +2727,53 @@ bool FillVideoChatMenu(
|
||||||
return has || manager;
|
return has || manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FillSenderUserpicMenu(
|
||||||
|
not_null<SessionController*> controller,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Ui::InputField *fieldForMention,
|
||||||
|
Dialogs::Key searchInEntry,
|
||||||
|
const PeerMenuCallback &addAction) {
|
||||||
|
const auto group = (peer->isChat() || peer->isMegagroup());
|
||||||
|
const auto channel = peer->isChannel();
|
||||||
|
const auto viewProfileText = group
|
||||||
|
? tr::lng_context_view_group(tr::now)
|
||||||
|
: channel
|
||||||
|
? tr::lng_context_view_channel(tr::now)
|
||||||
|
: tr::lng_context_view_profile(tr::now);
|
||||||
|
addAction(viewProfileText, [=] {
|
||||||
|
controller->showPeerInfo(peer, Window::SectionShow::Way::Forward);
|
||||||
|
}, channel ? &st::menuIconInfo : &st::menuIconProfile);
|
||||||
|
|
||||||
|
const auto showHistoryText = group
|
||||||
|
? tr::lng_context_open_group(tr::now)
|
||||||
|
: channel
|
||||||
|
? tr::lng_context_open_channel(tr::now)
|
||||||
|
: tr::lng_profile_send_message(tr::now);
|
||||||
|
addAction(showHistoryText, [=] {
|
||||||
|
controller->showPeerHistory(peer, Window::SectionShow::Way::Forward);
|
||||||
|
}, channel ? &st::menuIconChannel : &st::menuIconChatBubble);
|
||||||
|
|
||||||
|
const auto username = peer->username();
|
||||||
|
const auto mention = !username.isEmpty() || peer->isUser();
|
||||||
|
if (const auto guard = mention ? fieldForMention : nullptr) {
|
||||||
|
addAction(tr::lng_context_mention(tr::now), crl::guard(guard, [=] {
|
||||||
|
if (!username.isEmpty()) {
|
||||||
|
fieldForMention->insertTag('@' + username);
|
||||||
|
} else {
|
||||||
|
fieldForMention->insertTag(
|
||||||
|
peer->shortName(),
|
||||||
|
PrepareMentionTag(peer->asUser()));
|
||||||
|
}
|
||||||
|
}), &st::menuIconUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchInEntry) {
|
||||||
|
addAction(tr::lng_context_search_from(tr::now), [=] {
|
||||||
|
controller->searchInChat(searchInEntry, peer);
|
||||||
|
}, &st::menuIconSearch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IsUnreadThread(not_null<Data::Thread*> thread) {
|
bool IsUnreadThread(not_null<Data::Thread*> thread) {
|
||||||
return thread->chatListBadgesState().unread;
|
return thread->chatListBadgesState().unread;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace Dialogs {
|
||||||
class MainList;
|
class MainList;
|
||||||
struct EntryState;
|
struct EntryState;
|
||||||
struct UnreadState;
|
struct UnreadState;
|
||||||
|
class Key;
|
||||||
} // namespace Dialogs
|
} // namespace Dialogs
|
||||||
|
|
||||||
namespace ChatHelpers {
|
namespace ChatHelpers {
|
||||||
|
@ -64,6 +65,13 @@ bool FillVideoChatMenu(
|
||||||
Dialogs::EntryState request,
|
Dialogs::EntryState request,
|
||||||
const PeerMenuCallback &addAction);
|
const PeerMenuCallback &addAction);
|
||||||
|
|
||||||
|
void FillSenderUserpicMenu(
|
||||||
|
not_null<SessionController*> controller,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Ui::InputField *fieldForMention,
|
||||||
|
Dialogs::Key searchInEntry,
|
||||||
|
const PeerMenuCallback &addAction);
|
||||||
|
|
||||||
void MenuAddMarkAsReadAllChatsAction(
|
void MenuAddMarkAsReadAllChatsAction(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
const PeerMenuCallback &addAction);
|
const PeerMenuCallback &addAction);
|
||||||
|
|
|
@ -1175,14 +1175,17 @@ void SessionNavigation::showPollResults(
|
||||||
showSection(std::make_shared<Info::Memento>(poll, contextId), params);
|
showSection(std::make_shared<Info::Memento>(poll, contextId), params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionNavigation::searchInChat(Dialogs::Key inChat) {
|
void SessionNavigation::searchInChat(
|
||||||
searchMessages(QString(), inChat);
|
Dialogs::Key inChat,
|
||||||
|
PeerData *searchFrom) {
|
||||||
|
searchMessages(QString(), inChat, searchFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionNavigation::searchMessages(
|
void SessionNavigation::searchMessages(
|
||||||
const QString &query,
|
const QString &query,
|
||||||
Dialogs::Key inChat) {
|
Dialogs::Key inChat,
|
||||||
parentController()->content()->searchMessages(query, inChat);
|
PeerData *searchFrom) {
|
||||||
|
parentController()->content()->searchMessages(query, inChat, searchFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SessionNavigation::showToast(Ui::Toast::Config &&config)
|
auto SessionNavigation::showToast(Ui::Toast::Config &&config)
|
||||||
|
|
|
@ -247,8 +247,11 @@ public:
|
||||||
FullMsgId contextId,
|
FullMsgId contextId,
|
||||||
const SectionShow ¶ms = SectionShow());
|
const SectionShow ¶ms = SectionShow());
|
||||||
|
|
||||||
void searchInChat(Dialogs::Key inChat);
|
void searchInChat(Dialogs::Key inChat, PeerData *searchFrom = nullptr);
|
||||||
void searchMessages(const QString &query, Dialogs::Key inChat);
|
void searchMessages(
|
||||||
|
const QString &query,
|
||||||
|
Dialogs::Key inChat,
|
||||||
|
PeerData *searchFrom = nullptr);
|
||||||
|
|
||||||
void resolveBoostState(not_null<ChannelData*> channel);
|
void resolveBoostState(not_null<ChannelData*> channel);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue