Add userpics to the active call bar.

This commit is contained in:
John Preston 2020-11-29 16:12:46 +03:00
parent e3a73378e7
commit 5339523824
6 changed files with 97 additions and 14 deletions

View file

@ -500,3 +500,8 @@ groupCallMuteBottomSkip: 149px;
groupCallTopBarUserpicSize: 28px;
groupCallTopBarUserpicShift: 8px;
groupCallTopBarUserpicStroke: 2px;
groupCallTopBarJoin: RoundButton(defaultActiveButton) {
width: -30px;
height: 28px;
textTop: 5px;
}

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/chat/group_call_bar.h" // Ui::GroupCallBarContent.
#include "ui/layers/generic_box.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/text/format_values.h"
@ -18,7 +19,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "calls/calls_instance.h"
#include "calls/calls_signal_bars.h"
#include "calls/calls_group_panel.h" // LeaveGroupCallBox.
#include "history/view/history_view_group_call_tracker.h" // ContentByCall.
#include "data/data_user.h"
#include "data/data_group_call.h"
#include "data/data_channel.h"
#include "data/data_changes.h"
#include "main/main_session.h"
@ -104,7 +107,12 @@ TopBar::TopBar(
: object_ptr<SignalBars>(nullptr))
, _fullInfoLabel(this, st::callBarInfoLabel)
, _shortInfoLabel(this, st::callBarInfoLabel)
, _hangupLabel(this, st::callBarLabel, tr::lng_call_bar_hangup(tr::now).toUpper())
, _hangupLabel(_call
? object_ptr<Ui::LabelSimple>(
this,
st::callBarLabel,
tr::lng_call_bar_hangup(tr::now).toUpper())
: object_ptr<Ui::LabelSimple>(nullptr))
, _mute(this, st::callBarMuteToggle)
, _info(this)
, _hangup(this, st::callBarHangup) {
@ -136,8 +144,8 @@ void TopBar::initControls() {
update();
}, lifetime());
if (_groupCall) {
_groupCall->mutedValue(
if (const auto group = _groupCall.get()) {
group->mutedValue(
) | rpl::start_with_next([=](MuteState state) {
if (state == MuteState::ForceMuted) {
_mute->clearState();
@ -146,6 +154,8 @@ void TopBar::initControls() {
Qt::WA_TransparentForMouseEvents,
(state == MuteState::ForceMuted));
}, _mute->lifetime());
subscribeToMembersChanges(group);
}
if (const auto call = _call.get()) {
@ -187,6 +197,33 @@ void TopBar::initControls() {
updateDurationText();
}
void TopBar::subscribeToMembersChanges(not_null<GroupCall*> call) {
const auto channel = call->channel();
channel->session().changes().peerFlagsValue(
channel,
Data::PeerUpdate::Flag::GroupCall
) | rpl::map([=] {
return channel->call();
}) | rpl::filter([=](Data::GroupCall *real) {
const auto call = _groupCall.get();
return call && real && (real->id() == call->id());
}) | rpl::take(
1
) | rpl::map([=](not_null<Data::GroupCall*> real) {
return HistoryView::GroupCallTracker::ContentByCall(
real,
HistoryView::UserpicsInRowStyle{
.size = st::groupCallTopBarUserpicSize,
.shift = st::groupCallTopBarUserpicShift,
.stroke = st::groupCallTopBarUserpicStroke,
});
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](const Ui::GroupCallBarContent &content) {
_userpics = content.userpics;
update();
}, lifetime());
}
void TopBar::updateInfoLabels() {
setInfoLabels();
updateControlsGeometry();
@ -251,8 +288,12 @@ void TopBar::updateControlsGeometry() {
}
auto right = st::callBarRightSkip;
_hangupLabel->moveToRight(right, st::callBarLabelTop);
right += _hangupLabel->width();
if (_hangupLabel) {
_hangupLabel->moveToRight(right, st::callBarLabelTop);
right += _hangupLabel->width();
} else {
//right -= st::callBarRightSkip;
}
right += st::callBarHangup.width;
_hangup->setGeometryToRight(0, 0, right, height());
_info->setGeometryToLeft(
@ -283,6 +324,12 @@ void TopBar::updateControlsGeometry() {
void TopBar::paintEvent(QPaintEvent *e) {
Painter p(this);
p.fillRect(e->rect(), _muted ? st::callBarBgMuted : st::callBarBg);
if (!_userpics.isNull()) {
const auto imageSize = _userpics.size()
/ _userpics.devicePixelRatio();
const auto top = (height() - imageSize.height()) / 2;
p.drawImage(_mute->width(), top, _userpics);
}
}
TopBar::~TopBar() = default;

View file

@ -54,10 +54,13 @@ private:
void startDurationUpdateTimer(crl::time currentDuration);
void setMuted(bool mute);
void subscribeToMembersChanges(not_null<GroupCall*> call);
const base::weak_ptr<Call> _call;
const base::weak_ptr<GroupCall> _groupCall;
bool _muted = false;
QImage _userpics;
object_ptr<Ui::LabelSimple> _durationLabel;
object_ptr<SignalBars> _signalBars;
object_ptr<Ui::FlatLabel> _fullInfoLabel;

View file

@ -192,7 +192,18 @@ rpl::producer<Ui::GroupCallBarContent> GroupCallTracker::ContentByCall(
// Full kLimit of speaking userpics already.
return false;
}
// Add the new speaking to the place we found.
const auto added = state->userpics.insert(i, UserpicInRow{ user });
// Remove him from the tail, if he was there.
for (auto i = added + 1; i != state->userpics.end(); ++i) {
if (i->peer == user) {
state->userpics.erase(i);
break;
}
}
if (state->userpics.size() > kLimit) {
// Find last non-speaking userpic to remove. It must be there.
for (auto i = state->userpics.end() - 1; i != added; --i) {

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "lang/lang_keys.h"
#include "styles/style_chat.h"
#include "styles/style_calls.h"
#include "styles/palette.h"
#include <QtGui/QtEvents>
@ -23,6 +24,10 @@ GroupCallBar::GroupCallBar(
rpl::producer<GroupCallBarContent> content)
: _wrap(parent, object_ptr<RpWidget>(parent))
, _inner(_wrap.entity())
, _join(std::make_unique<RoundButton>(
_inner.get(),
tr::lng_group_call_join(),
st::groupCallTopBarJoin))
, _shadow(std::make_unique<PlainShadow>(_wrap.parentWidget())) {
_wrap.hide(anim::type::instant);
_shadow->hide();
@ -72,7 +77,6 @@ void GroupCallBar::setupInner() {
paint(p);
}, _inner->lifetime());
// Clicks.
_inner->setCursor(style::cur_pointer);
_inner->events(
@ -91,6 +95,16 @@ void GroupCallBar::setupInner() {
return rpl::empty_value();
}) | rpl::start_to_stream(_barClicks, _inner->lifetime());
rpl::combine(
_inner->widthValue(),
_join->widthValue()
) | rpl::start_with_next([=](int outerWidth, int) {
// Skip shadow of the bar above.
const auto top = (st::historyReplyHeight
- st::lineWidth
- _join->height()) / 2 + st::lineWidth;
_join->moveToRight(top, top, outerWidth);
}, _join->lifetime());
_wrap.geometryValue(
) | rpl::start_with_next([=](QRect rect) {
@ -106,10 +120,11 @@ void GroupCallBar::paint(Painter &p) {
if (!_content.userpics.isNull()) {
const auto imageSize = _content.userpics.size()
/ _content.userpics.devicePixelRatio();
p.drawImage(
left,
(_inner->height() - imageSize.height()) / 2,
_content.userpics);
// Skip shadow of the bar above.
const auto imageTop = (st::historyReplyHeight
- st::lineWidth
- imageSize.height()) / 2 + st::lineWidth;
p.drawImage(left, imageTop, _content.userpics);
left += imageSize.width() + st::msgReplyBarSkip;
}
const auto titleTop = st::msgReplyPadding.top();
@ -207,7 +222,7 @@ rpl::producer<> GroupCallBar::barClicks() const {
}
rpl::producer<> GroupCallBar::joinClicks() const {
return rpl::never<>();
return _join->clicks() | rpl::to_empty;
}
} // namespace Ui

View file

@ -15,6 +15,7 @@ class Painter;
namespace Ui {
class PlainShadow;
class RoundButton;
struct GroupCallBarContent {
int count = 0;
@ -53,9 +54,10 @@ private:
void setupInner();
void paint(Painter &p);
Ui::SlideWrap<> _wrap;
not_null<Ui::RpWidget*> _inner;
std::unique_ptr<Ui::PlainShadow> _shadow;
SlideWrap<> _wrap;
not_null<RpWidget*> _inner;
std::unique_ptr<RoundButton> _join;
std::unique_ptr<PlainShadow> _shadow;
rpl::event_stream<> _barClicks;
Fn<QRect(QRect)> _shadowGeometryPostprocess;
bool _shouldBeShown = false;