Show PeerShortInfoCover in group call context menu.

This commit is contained in:
John Preston 2021-10-22 18:33:58 +04:00
parent bcddda3cd3
commit d0606a3798
9 changed files with 195 additions and 21 deletions

View File

@ -258,6 +258,8 @@ PRIVATE
boxes/username_box.h
calls/group/calls_choose_join_as.cpp
calls/group/calls_choose_join_as.h
calls/group/calls_cover_item.cpp
calls/group/calls_cover_item.h
calls/group/calls_group_call.cpp
calls/group/calls_group_call.h
calls/group/calls_group_common.cpp

View File

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_text.h"
#include "media/streaming/media_streaming_instance.h"
#include "media/streaming/media_streaming_player.h"
#include "base/event_filter.h"
#include "lang/lang_keys.h"
#include "styles/style_layers.h"
#include "styles/style_info.h"
@ -93,6 +94,8 @@ PeerShortInfoCover::PeerShortInfoCover(
, _statusStyle(std::make_unique<CustomLabelStyle>(_st.status))
, _status(_widget.get(), std::move(status), _statusStyle->st)
, _videoPaused(std::move(videoPaused)) {
_widget->setCursor(_cursor);
_widget->resize(_st.size, _st.size);
std::move(
@ -112,21 +115,23 @@ PeerShortInfoCover::PeerShortInfoCover(
paint(p);
}, lifetime());
_widget->events(
) | rpl::filter([=](not_null<QEvent*> e) {
return (e->type() == QEvent::MouseButtonPress)
|| (e->type() == QEvent::MouseButtonDblClick);
}) | rpl::start_with_next([=](not_null<QEvent*> e) {
base::install_event_filter(_widget.get(), [=](not_null<QEvent*> e) {
if (e->type() != QEvent::MouseButtonPress
&& e->type() != QEvent::MouseButtonDblClick) {
return base::EventFilterResult::Continue;
}
const auto mouse = static_cast<QMouseEvent*>(e.get());
const auto x = mouse->pos().x();
if (mouse->button() != Qt::LeftButton) {
return;
return base::EventFilterResult::Continue;
} else if (/*_index > 0 && */x < _st.size / 3) {
_moveRequests.fire(-1);
} else if (/*_index + 1 < _count && */x >= _st.size / 3) {
_moveRequests.fire(1);
}
}, lifetime());
e->accept();
return base::EventFilterResult::Cancel;
});
_name->moveToLeft(
_st.namePosition.x(),
@ -148,6 +153,10 @@ PeerShortInfoCover::PeerShortInfoCover(
PeerShortInfoCover::~PeerShortInfoCover() = default;
not_null<Ui::RpWidget*> PeerShortInfoCover::widget() const {
return _widget;
}
object_ptr<Ui::RpWidget> PeerShortInfoCover::takeOwned() {
return std::move(_owned);
}

View File

@ -62,6 +62,7 @@ public:
Fn<bool()> videoPaused);
~PeerShortInfoCover();
[[nodiscard]] not_null<Ui::RpWidget*> widget() const;
[[nodiscard]] object_ptr<Ui::RpWidget> takeOwned();
void setScrollTop(int scrollTop);

View File

@ -86,18 +86,20 @@ void ProcessUserpic(
st::shortInfoWidth * style::DevicePixelRatio(),
ImageRoundRadius::None),
false);
state->current.photoLoadingProgress = 1.;
state->photoView = nullptr;
return;
}
peer->loadUserpic();
state->current.photoLoadingProgress = 0.;
const auto image = state->userpicView->image();
if (!image) {
state->current.photoLoadingProgress = 0.;
state->current.photo = QImage();
state->waitingLoad = true;
return;
}
GenerateImage(state, image, true);
state->current.photoLoadingProgress = peer->userpicPhotoId() ? 0. : 1.;
state->photoView = nullptr;
}
@ -265,10 +267,6 @@ void ProcessFullPhoto(
});
}
void ProcessOld(not_null<PeerData*> peer, not_null<UserpicState*> state) {
}
void ValidatePhotoId(
not_null<UserpicState*> state,
PhotoId oldUserpicPhotoId) {
@ -357,12 +355,8 @@ bool ProcessCurrent(
return true;
}
struct UserpicResult {
rpl::producer<PeerShortInfoUserpic> value;
Fn<void(int)> move;
};
[[nodiscard]] UserpicResult UserpicValue(not_null<PeerData*> peer) {
[[nodiscard]] PreparedShortInfoUserpic UserpicValue(
not_null<PeerData*> peer) {
const auto moveRequests = std::make_shared<rpl::event_stream<int>>();
auto move = [=](int shift) {
moveRequests->fire_copy(shift);
@ -463,3 +457,11 @@ object_ptr<Ui::BoxContent> PrepareShortInfoBox(
open,
videoIsPaused);
}
rpl::producer<QString> PrepareShortInfoStatus(not_null<PeerData*> peer) {
return StatusValue(peer);
}
PreparedShortInfoUserpic PrepareShortInfoUserpic(not_null<PeerData*> peer) {
return UserpicValue(peer);
}

View File

@ -19,6 +19,13 @@ namespace Window {
class SessionNavigation;
} // namespace Window
struct PeerShortInfoUserpic;
struct PreparedShortInfoUserpic {
rpl::producer<PeerShortInfoUserpic> value;
Fn<void(int)> move;
};
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
not_null<PeerData*> peer,
Fn<void()> open,
@ -27,3 +34,9 @@ class SessionNavigation;
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShortInfoBox(
not_null<PeerData*> peer,
not_null<Window::SessionNavigation*> navigation);
[[nodiscard]] rpl::producer<QString> PrepareShortInfoStatus(
not_null<PeerData*> peer);
[[nodiscard]] PreparedShortInfoUserpic PrepareShortInfoUserpic(
not_null<PeerData*> peer);

View File

@ -10,6 +10,7 @@ using "ui/basic.style";
using "ui/widgets/widgets.style";
using "ui/layers/layers.style";
using "ui/chat/chat.style"; // GroupCallUserpics
using "info/info.style"; // ShortInfoCover
using "window/window.style";
CallSignalBars {
@ -542,6 +543,24 @@ groupCallPopupVolumeMenu: Menu(groupCallMenu) {
widthMin: 210px;
itemBgOver: groupCallMenuBg;
}
groupCallMenuCoverSize: 240px;
groupCallPopupCoverMenu: Menu(groupCallMenu) {
widthMin: groupCallMenuCoverSize;
widthMax: groupCallMenuCoverSize;
itemBgOver: groupCallMenuBg;
}
groupCallPopupMenuWithCover: PopupMenu(groupCallPopupMenu) {
scrollPadding: margins(0px, 0px, 0px, 8px);
menu: Menu(groupCallMenu) {
widthMin: groupCallMenuCoverSize;
widthMax: groupCallMenuCoverSize;
}
}
groupCallMenuCover: ShortInfoCover(shortInfoCover) {
size: groupCallMenuCoverSize;
namePosition: point(17px, 28px);
statusPosition: point(17px, 8px);
}
groupCallRecordingTimerPadding: margins(0px, 4px, 0px, 4px);
groupCallRecordingTimerFont: font(12px);

View File

@ -0,0 +1,59 @@
/*
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 "calls/group/calls_cover_item.h"
#include "boxes/peers/prepare_short_info_box.h"
#include "styles/style_calls.h"
#include "styles/style_info.h"
namespace Calls {
namespace {
} // namespace
CoverItem::CoverItem(
not_null<RpWidget*> parent,
const style::Menu &stMenu,
const style::ShortInfoCover &st,
rpl::producer<QString> name,
rpl::producer<QString> status,
PreparedShortInfoUserpic userpic)
: Ui::Menu::ItemBase(parent, stMenu)
, _cover(
this,
st,
std::move(name),
std::move(status),
std::move(userpic.value),
[] { return false; })
, _dummyAction(new QAction(parent))
, _st(st) {
setPointerCursor(false);
initResizeHook(parent->sizeValue());
enableMouseSelecting();
enableMouseSelecting(_cover.widget());
_cover.widget()->move(0, 0);
_cover.moveRequests(
) | rpl::start_with_next(userpic.move, lifetime());
}
not_null<QAction*> CoverItem::action() const {
return _dummyAction;
}
bool CoverItem::isEnabled() const {
return false;
}
int CoverItem::contentHeight() const {
return _st.size + st::groupCallMenu.separatorPadding.bottom();
}
} // namespace Calls

View File

@ -0,0 +1,51 @@
/*
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
#include "ui/rp_widget.h"
#include "ui/widgets/menu/menu_item_base.h"
#include "boxes/peers/peer_short_info_box.h"
struct PreparedShortInfoUserpic;
namespace style {
struct ShortInfoCover;
} // namespace style
namespace Calls {
namespace Group {
struct MuteRequest;
struct VolumeRequest;
struct ParticipantState;
} // namespace Group
class CoverItem final : public Ui::Menu::ItemBase {
public:
CoverItem(
not_null<RpWidget*> parent,
const style::Menu &stMenu,
const style::ShortInfoCover &st,
rpl::producer<QString> name,
rpl::producer<QString> status,
PreparedShortInfoUserpic userpic);
not_null<QAction*> action() const override;
bool isEnabled() const override;
private:
int contentHeight() const override;
const PeerShortInfoCover _cover;
const not_null<QAction*> _dummyAction;
const style::ShortInfoCover &_st;
};
} // namespace Calls

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "calls/group/calls_group_members.h"
#include "calls/group/calls_cover_item.h"
#include "calls/group/calls_group_call.h"
#include "calls/group/calls_group_menu.h"
#include "calls/group/calls_volume_item.h"
@ -31,7 +32,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "main/main_account.h" // account().appConfig().
#include "main/main_app_config.h" // appConfig().get<double>().
#include "info/profile/info_profile_values.h" // Info::Profile::NameValue.
#include "boxes/peers/edit_participants_box.h" // SubscribeToMigration.
#include "boxes/peers/prepare_short_info_box.h" // PrepareShortInfo...
#include "window/window_controller.h" // Controller::sessionController.
#include "window/window_session_controller.h"
#include "webrtc/webrtc_video_track.h"
@ -1189,6 +1192,7 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
const auto muteState = real->state();
const auto muted = (muteState == Row::State::Muted)
|| (muteState == Row::State::RaisedHand);
const auto addCover = true;
const auto addVolumeItem = !muted || isMe(participantPeer);
const auto admin = IsGroupCallAdmin(_peer, participantPeer);
const auto session = &_peer->session();
@ -1213,7 +1217,9 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
auto result = base::make_unique_q<Ui::PopupMenu>(
parent,
(addVolumeItem
(addCover
? st::groupCallPopupMenuWithCover
: addVolumeItem
? st::groupCallPopupMenuWithVolume
: st::groupCallPopupMenu));
const auto weakMenu = Ui::MakeWeak(result.get());
@ -1247,6 +1253,18 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
_kickParticipantRequests.fire_copy(participantPeer);
});
if (addCover) {
result->addAction(base::make_unique_q<CoverItem>(
result->menu(),
st::groupCallPopupCoverMenu,
st::groupCallMenuCover,
Info::Profile::NameValue(
participantPeer
) | rpl::map([](const auto &text) { return text.text; }),
PrepareShortInfoStatus(participantPeer),
PrepareShortInfoUserpic(participantPeer)));
}
if (const auto real = _call->lookupReal()) {
auto oneFound = false;
auto hasTwoOrMore = false;
@ -1357,7 +1375,7 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
removeFromVoiceChat));
}
}
if (result->empty()) {
if (result->actions().size() < (addCover ? 2 : 1)) {
return nullptr;
}
return result;
@ -1451,7 +1469,7 @@ void Members::Controller::addMuteActionsToContextMenu(
}
}, volumeItem->lifetime());
if (!menu->empty()) {
if (menu->actions().size() > 1) { // First - cover.
menu->addSeparator();
}