mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Top peers context menu.
This commit is contained in:
parent
56e28feb00
commit
19ae76d8de
8 changed files with 126 additions and 18 deletions
|
@ -56,6 +56,19 @@ rpl::producer<> TopPeers::updates() const {
|
|||
return _updates.events();
|
||||
}
|
||||
|
||||
void TopPeers::remove(not_null<PeerData*> peer) {
|
||||
const auto i = ranges::find(_list, peer, &TopPeer::peer);
|
||||
if (i != end(_list)) {
|
||||
_list.erase(i);
|
||||
_updates.fire({});
|
||||
}
|
||||
|
||||
_requestId = _session->api().request(MTPcontacts_ResetTopPeerRating(
|
||||
MTP_topPeerCategoryCorrespondents(),
|
||||
peer->input
|
||||
)).send();
|
||||
}
|
||||
|
||||
void TopPeers::increment(not_null<PeerData*> peer, TimeId date) {
|
||||
if (date <= _lastReceivedDate) {
|
||||
return;
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
[[nodiscard]] bool disabled() const;
|
||||
[[nodiscard]] rpl::producer<> updates() const;
|
||||
|
||||
void remove(not_null<PeerData*> peer);
|
||||
void increment(not_null<PeerData*> peer, TimeId date);
|
||||
void reload();
|
||||
|
||||
|
|
|
@ -1027,7 +1027,7 @@ void Widget::updateControlsVisibility(bool fast) {
|
|||
_suggestions->show();
|
||||
}
|
||||
updateStoriesVisibility();
|
||||
if ((_openedFolder || _openedForum) && _searchHasFocus.current()) {
|
||||
if ((_openedFolder || _openedForum) && _searchHasFocus) {
|
||||
setInnerFocus();
|
||||
}
|
||||
if (_updateTelegram) {
|
||||
|
@ -1066,7 +1066,7 @@ void Widget::updateControlsVisibility(bool fast) {
|
|||
if (_hideChildListCanvas) {
|
||||
_hideChildListCanvas->show();
|
||||
}
|
||||
if (_childList && _searchHasFocus.current()) {
|
||||
if (_childList && _searchHasFocus) {
|
||||
setInnerFocus();
|
||||
}
|
||||
updateLockUnlockPosition();
|
||||
|
@ -1090,16 +1090,26 @@ void Widget::updateLockUnlockPosition() {
|
|||
|
||||
void Widget::updateHasFocus(not_null<QWidget*> focused) {
|
||||
const auto has = (focused == _search.data());
|
||||
if (_searchHasFocus.current() != has) {
|
||||
_searchHasFocus = (focused == _search.data());
|
||||
updateStoriesVisibility();
|
||||
updateForceDisplayWide();
|
||||
updateSuggestions(anim::type::normal);
|
||||
if (_searchHasFocus != has) {
|
||||
_searchHasFocus = has;
|
||||
const auto update = [=] {
|
||||
updateStoriesVisibility();
|
||||
updateForceDisplayWide();
|
||||
updateSuggestions(anim::type::normal);
|
||||
};
|
||||
if (has) {
|
||||
update();
|
||||
} else {
|
||||
// Search field may loose focus from the destructor of some
|
||||
// widget, in that case we don't want to destroy _suggestions
|
||||
// syncrhonously, because it may lead to a crash.
|
||||
crl::on_main(this, update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::updateSuggestions(anim::type animated) {
|
||||
const auto suggest = _searchHasFocus.current()
|
||||
const auto suggest = _searchHasFocus
|
||||
&& !_searchInChat
|
||||
&& (_inner->state() == WidgetState::Default);
|
||||
if (!suggest && _suggestions) {
|
||||
|
@ -1108,6 +1118,7 @@ void Widget::updateSuggestions(anim::type animated) {
|
|||
} else if (suggest && !_suggestions) {
|
||||
_suggestions = std::make_unique<Suggestions>(
|
||||
this,
|
||||
controller(),
|
||||
TopPeersContent(&session()));
|
||||
|
||||
_suggestions->topPeerChosen(
|
||||
|
@ -1563,7 +1574,7 @@ void Widget::updateStoriesVisibility() {
|
|||
|| _openedForum
|
||||
|| !_widthAnimationCache.isNull()
|
||||
|| _childList
|
||||
|| _searchHasFocus.current()
|
||||
|| _searchHasFocus
|
||||
|| !_search->getLastText().isEmpty()
|
||||
|| _searchInChat
|
||||
|| _stories->empty();
|
||||
|
@ -1681,7 +1692,7 @@ void Widget::slideFinished() {
|
|||
_shownProgressValue = 1.;
|
||||
updateControlsVisibility(true);
|
||||
if ((!_subsectionTopBar || !_subsectionTopBar->searchHasFocus())
|
||||
&& !_searchHasFocus.current()) {
|
||||
&& !_searchHasFocus) {
|
||||
controller()->widget()->setInnerFocus();
|
||||
}
|
||||
}
|
||||
|
@ -2524,7 +2535,7 @@ void Widget::applySearchUpdate(bool force) {
|
|||
}
|
||||
|
||||
void Widget::updateForceDisplayWide() {
|
||||
controller()->setChatsForceDisplayWide(_searchHasFocus.current()
|
||||
controller()->setChatsForceDisplayWide(_searchHasFocus
|
||||
|| !_search->getLastText().isEmpty()
|
||||
|| _searchInChat);
|
||||
}
|
||||
|
@ -3258,7 +3269,7 @@ bool Widget::cancelSearch() {
|
|||
_inner->clearFilter();
|
||||
clearSearchField();
|
||||
applySearchUpdate();
|
||||
if (!_searchInChat && _searchHasFocus.current()) {
|
||||
if (!_searchInChat && _searchHasFocus) {
|
||||
setFocus();
|
||||
}
|
||||
return clearingQuery || clearingInChat;
|
||||
|
|
|
@ -300,7 +300,7 @@ private:
|
|||
std::vector<Data::ReactionId> _searchTags;
|
||||
rpl::lifetime _searchTagsLifetime;
|
||||
QString _lastSearchText;
|
||||
rpl::variable<bool> _searchHasFocus = false;
|
||||
bool _searchHasFocus = false;
|
||||
|
||||
rpl::event_stream<rpl::producer<Stories::Content>> _storiesContents;
|
||||
base::flat_map<PeerId, Ui::PeerUserpicView> _storiesUserpicsViewsHidden;
|
||||
|
|
|
@ -22,13 +22,55 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/dynamic_thumbnails.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
|
||||
namespace Dialogs {
|
||||
namespace {
|
||||
|
||||
void FillTopPeerMenu(
|
||||
not_null<Window::SessionController*> controller,
|
||||
const ShowTopPeerMenuRequest &request,
|
||||
Fn<void(not_null<PeerData*>)> remove) {
|
||||
const auto owner = &controller->session().data();
|
||||
const auto peer = owner->peer(PeerId(request.id));
|
||||
const auto &add = request.callback;
|
||||
const auto group = peer->isMegagroup();
|
||||
const auto channel = peer->isChannel();
|
||||
|
||||
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);
|
||||
add(showHistoryText, [=] {
|
||||
controller->showPeerHistory(peer);
|
||||
}, channel ? &st::menuIconChannel : &st::menuIconChatBubble);
|
||||
|
||||
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);
|
||||
add(viewProfileText, [=] {
|
||||
controller->showPeerInfo(peer);
|
||||
}, channel ? &st::menuIconInfo : &st::menuIconProfile);
|
||||
|
||||
add({
|
||||
.text = tr::lng_recent_remove(tr::now),
|
||||
.handler = [=] { remove(peer); },
|
||||
.icon = &st::menuIconDeleteAttention,
|
||||
.isAttention = true,
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Suggestions::Suggestions(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
rpl::producer<TopPeersList> topPeers)
|
||||
: RpWidget(parent)
|
||||
, _scroll(std::make_unique<Ui::ElasticScroll>(this))
|
||||
|
@ -45,6 +87,15 @@ Suggestions::Suggestions(
|
|||
_topPeers->clicks() | rpl::start_with_next([=](uint64 peerIdRaw) {
|
||||
_topPeerChosen.fire(PeerId(peerIdRaw));
|
||||
}, _topPeers->lifetime());
|
||||
|
||||
_topPeers->showMenuRequests(
|
||||
) | rpl::start_with_next([=](const ShowTopPeerMenuRequest &request) {
|
||||
const auto remove = crl::guard(this, [=](not_null<PeerData*> peer) {
|
||||
peer->session().topPeers().remove(peer);
|
||||
_topPeers->removeLocally(peer->id.value);
|
||||
});
|
||||
FillTopPeerMenu(controller, request, remove);
|
||||
}, _topPeers->lifetime());
|
||||
}
|
||||
|
||||
Suggestions::~Suggestions() = default;
|
||||
|
@ -111,6 +162,9 @@ rpl::producer<TopPeersList> TopPeersContent(
|
|||
const auto now = base::unixtime::now();
|
||||
for (const auto &peer : top) {
|
||||
const auto user = peer->asUser();
|
||||
if (user->isInaccessible()) {
|
||||
continue;
|
||||
}
|
||||
const auto self = user && user->isSelf();
|
||||
const auto history = peer->owner().history(peer);
|
||||
const auto badges = history->chatListBadgesState();
|
||||
|
|
|
@ -22,12 +22,17 @@ template <typename Widget>
|
|||
class SlideWrap;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Dialogs {
|
||||
|
||||
class Suggestions final : public Ui::RpWidget {
|
||||
public:
|
||||
Suggestions(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
rpl::producer<TopPeersList> topPeers);
|
||||
~Suggestions();
|
||||
|
||||
|
|
|
@ -212,13 +212,29 @@ auto TopPeersStrip::showMenuRequests() const
|
|||
return _showMenuRequests.events();
|
||||
}
|
||||
|
||||
void TopPeersStrip::removeLocally(uint64 id) {
|
||||
_removed.emplace(id);
|
||||
const auto i = ranges::find(_entries, id, &Entry::id);
|
||||
if (i == end(_entries)) {
|
||||
return;
|
||||
} else if (i->subscribed) {
|
||||
i->userpic->subscribeToUpdates(nullptr);
|
||||
}
|
||||
_entries.erase(i);
|
||||
updateScrollMax();
|
||||
if (_entries.empty()) {
|
||||
_empty = true;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void TopPeersStrip::apply(const TopPeersList &list) {
|
||||
auto now = std::vector<Entry>();
|
||||
|
||||
if (list.entries.empty()) {
|
||||
_empty = true;
|
||||
}
|
||||
for (const auto &entry : list.entries) {
|
||||
if (_removed.contains(entry.id)) {
|
||||
continue;
|
||||
}
|
||||
const auto i = ranges::find(_entries, entry.id, &Entry::id);
|
||||
if (i != end(_entries)) {
|
||||
now.push_back(base::take(*i));
|
||||
|
@ -227,6 +243,9 @@ void TopPeersStrip::apply(const TopPeersList &list) {
|
|||
}
|
||||
apply(now.back(), entry);
|
||||
}
|
||||
if (now.empty()) {
|
||||
_empty = true;
|
||||
}
|
||||
for (auto &entry : _entries) {
|
||||
if (entry.subscribed) {
|
||||
entry.userpic->subscribeToUpdates(nullptr);
|
||||
|
@ -234,6 +253,7 @@ void TopPeersStrip::apply(const TopPeersList &list) {
|
|||
}
|
||||
}
|
||||
_entries = std::move(now);
|
||||
updateScrollMax();
|
||||
unsubscribeUserpics();
|
||||
if (!_entries.empty()) {
|
||||
_empty = false;
|
||||
|
@ -289,9 +309,10 @@ void TopPeersStrip::paintEvent(QPaintEvent *e) {
|
|||
const auto single = st.photoLeft * 2 + st.photo;
|
||||
|
||||
const auto from = std::min(_scrollLeft / single, int(_entries.size()));
|
||||
const auto till = std::max(
|
||||
const auto till = std::clamp(
|
||||
(_scrollLeft + width() + single - 1) / single + 1,
|
||||
from);
|
||||
from,
|
||||
int(_entries.size()));
|
||||
|
||||
auto x = -_scrollLeft + from * single;
|
||||
for (auto i = from; i != till; ++i) {
|
||||
|
|
|
@ -49,6 +49,8 @@ public:
|
|||
[[nodiscard]] auto showMenuRequests() const
|
||||
-> rpl::producer<ShowTopPeerMenuRequest>;
|
||||
|
||||
void removeLocally(uint64 id);
|
||||
|
||||
private:
|
||||
struct Entry;
|
||||
|
||||
|
@ -73,6 +75,7 @@ private:
|
|||
|
||||
std::vector<Entry> _entries;
|
||||
rpl::variable<bool> _empty = true;
|
||||
base::flat_set<uint64> _removed;
|
||||
|
||||
rpl::event_stream<uint64> _clicks;
|
||||
rpl::event_stream<ShowTopPeerMenuRequest> _showMenuRequests;
|
||||
|
|
Loading…
Add table
Reference in a new issue