Nice three-button narrow mode with gradient fading.

This commit is contained in:
John Preston 2021-05-21 17:15:45 +04:00
parent c12a50544e
commit 385b98ff3d
7 changed files with 310 additions and 92 deletions

View file

@ -195,8 +195,8 @@ callMuteButtonLabel: FlatLabel(defaultFlatLabel) {
}
}
callMuteButtonActiveInner: IconButton {
width: 136px;
height: 165px;
width: 112px;
height: 138px;
}
callMuteButtonSmallActiveInner: IconButton {
width: 68px;
@ -205,7 +205,7 @@ callMuteButtonSmallActiveInner: IconButton {
callMuteButtonActive: CallButton {
button: callMuteButtonActiveInner;
bg: groupCallLive1;
bgSize: 100px;
bgSize: 77px;
bgPosition: point(18px, 18px);
outerRadius: 18px;
outerBg: callAnswerBgOuter;
@ -221,10 +221,10 @@ callMuteButton: CallMuteButton {
sublabel: FlatLabel(defaultFlatLabel) {
textFg: groupCallMemberNotJoinedStatus;
}
labelsSkip: 5px;
sublabelSkip: 19px;
lottieSize: size(67px, 67px);
lottieTop: 35px;
labelsSkip: 8px;
sublabelSkip: 14px;
lottieSize: size(54px, 54px);
lottieTop: 31px;
}
callMuteButtonSmallActive: CallButton(callMuteButtonActive) {
button: callMuteButtonSmallActiveInner;
@ -685,7 +685,6 @@ groupCallTitleTop: 8px;
groupCallSubtitleTop: 26px;
groupCallWideVideoTop: 24px;
groupCallMembersMargin: margins(16px, 16px, 16px, 28px);
groupCallAddMember: SettingsButton(defaultSettingsButton) {
textFg: groupCallMemberNotJoinedStatus;
textFgOver: groupCallMemberNotJoinedStatus;
@ -780,6 +779,10 @@ groupCallSettingsInner: IconButton(callButton) {
groupCallShareInner: IconButton(groupCallSettingsInner) {
icon: icon {{ "calls/group_calls_share", groupCallIconFg }};
}
groupCallVideoInner: IconButton(groupCallSettingsInner) {
icon: icon {{ "calls/call_camera_muted", groupCallIconFg }};
iconPosition: point(-1px, 16px);
}
groupCallHangupInner: IconButton(callButton) {
icon: icon {{ "calls/call_discard", groupCallIconFg }};
ripple: RippleAnimation(defaultRippleAnimation) {
@ -792,6 +795,15 @@ groupCallSettings: CallButton(callMicrophoneMute) {
groupCallShare: CallButton(groupCallSettings) {
button: groupCallShareInner;
}
groupCallVideo: CallButton(groupCallSettings) {
button: groupCallVideoInner;
}
groupCallVideoInnerActive: IconButton(groupCallVideoInner) {
icon: icon {{ "calls/call_camera_active", groupCallIconFg }};
}
groupCallVideoActive: CallButton(groupCallVideo) {
button: groupCallVideoInnerActive;
}
groupCallHangup: CallButton(callHangup) {
button: groupCallHangupInner;
bg: groupCallLeaveBg;
@ -813,17 +825,14 @@ groupCallHangupSmall: CallButton(groupCallHangup) {
height: 76px;
}
}
groupCallVideoSmallInner: IconButton(groupCallSettingsInner) {
icon: icon {{ "calls/call_camera_muted", groupCallIconFg }};
iconPosition: point(-1px, 16px);
height: 76px;
}
groupCallVideoSmall: CallButton(groupCallShareSmall) {
button: groupCallVideoSmallInner;
button: IconButton(groupCallVideoInner) {
height: 76px;
}
}
groupCallVideoActiveSmall: CallButton(groupCallVideoSmall) {
button: IconButton(groupCallVideoSmallInner) {
icon: icon {{ "calls/call_camera_active", groupCallIconFg }};
button: IconButton(groupCallVideoInnerActive) {
height: 76px;
}
}
groupCallScreenShareSmall: CallButton(groupCallShareSmall) {
@ -832,15 +841,20 @@ groupCallScreenShareSmall: CallButton(groupCallShareSmall) {
height: 76px;
}
}
groupCallButtonSkip: 43px;
groupCallButtonSkip: 40px;
groupCallButtonSkipSmall: 4px;
groupCallButtonBottomSkip: 145px;
groupCallButtonBottomSkip: 113px;
groupCallButtonBottomSkipSmall: 95px;
groupCallButtonBottomSkipWide: 122px;
groupCallMembersBottomSkipSmall: 72px;
groupCallControlsBackMargin: margins(2px, 2px, 2px, 2px);
groupCallControlsBackRadius: 12px;
groupCallMuteBottomSkip: 160px;
groupCallMuteBottomSkip: 116px;
groupCallMembersMargin: margins(16px, 16px, 16px, 60px);
groupCallMembersBottomSkip: 80px;
groupCallMembersShadowHeight: 160px;
groupCallMembersFadeSkip: 10px;
groupCallMembersFadeHeight: 100px;
groupCallTopBarUserpics: GroupCallUserpics {
size: 28px;

View file

@ -438,16 +438,27 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
_track.row->name().drawLeftElided(p, nameLeft, nameTop, hasWidth, width);
}
QImage GenerateShadow(int height, int topAlpha, int bottomAlpha) {
QImage GenerateShadow(
int height,
int topAlpha,
int bottomAlpha,
QColor color) {
Expects(topAlpha >= 0 && topAlpha < 256);
Expects(bottomAlpha >= 0 && bottomAlpha < 256);
Expects(height * style::DevicePixelRatio() < 65536);
const auto base = (uint32(color.red()) << 16)
| (uint32(color.green()) << 8)
| uint32(color.blue());
const auto premultiplied = (topAlpha == bottomAlpha) || !base;
auto result = QImage(
QSize(1, height * style::DevicePixelRatio()),
QImage::Format_ARGB32_Premultiplied);
(premultiplied
? QImage::Format_ARGB32_Premultiplied
: QImage::Format_ARGB32));
if (topAlpha == bottomAlpha) {
result.fill(QColor(0, 0, 0, topAlpha));
color.setAlpha(topAlpha);
result.fill(color);
return result;
}
constexpr auto kShift = 16;
@ -460,13 +471,17 @@ QImage GenerateShadow(int height, int topAlpha, int bottomAlpha) {
auto ints = reinterpret_cast<uint32*>(result.bits());
if (topAlpha < bottomAlpha) {
for (auto i = uint32(0); i != till; i += step) {
*ints++ = ((topAlpha + (i >> kShift)) << 24);
*ints++ = base | ((topAlpha + (i >> kShift)) << 24);
}
} else {
for (auto i = uint32(0); i != till; i += step) {
*ints++ = ((topAlpha - (i >> kShift)) << 24);
*ints++ = base | ((topAlpha - (i >> kShift)) << 24);
}
}
if (!premultiplied) {
result = std::move(result).convertToFormat(
QImage::Format_ARGB32_Premultiplied);
}
return result;
}

View file

@ -114,6 +114,7 @@ private:
[[nodiscard]] QImage GenerateShadow(
int height,
int topAlpha,
int bottomAlpha);
int bottomAlpha,
QColor color = QColor(0, 0, 0));
} // namespace Calls::Group

View file

@ -1677,9 +1677,6 @@ auto Members::kickParticipantRequests() const
}
int Members::desiredHeight() const {
const auto addMember = _addMemberButton.current();
const auto top = _pinnedVideoWrap->height()
+ (addMember ? addMember->height() : 0);
const auto count = [&] {
if (const auto real = _call->lookupReal()) {
return real->fullCount();
@ -1690,16 +1687,18 @@ int Members::desiredHeight() const {
const auto single = /*(_mode.current() == PanelMode::Wide)
? (st::groupCallNarrowSize.height() + st::groupCallNarrowRowSkip * 2)
: */st::groupCallMembersList.item.height;
return top
const auto desired = (_layout->height() - _list->height())
+ (use * single)
+ (use ? st::lineWidth : 0);
return std::max(height(), desired);
}
rpl::producer<int> Members::desiredHeightValue() const {
return rpl::combine(
heightValue(),
_addMemberButton.value(),
_listController->fullCountValue()
_listController->fullCountValue(),
_mode.value()
) | rpl::map([=] {
return desiredHeight();
});
@ -1810,6 +1809,16 @@ void Members::setMode(PanelMode mode) {
// : PeerListContent::Mode::Default);
}
QRect Members::getInnerGeometry() const {
const auto addMembers = _addMemberButton.current();
const auto add = addMembers ? addMembers->height() : 0;
return QRect(
0,
-_scroll->scrollTop(),
width(),
_list->y() + _list->height());
}
rpl::producer<int> Members::fullCountValue() const {
return _listController->fullCountValue();
}
@ -1817,10 +1826,19 @@ rpl::producer<int> Members::fullCountValue() const {
void Members::setupList() {
_listController->setStyleOverrides(&st::groupCallMembersList);
_list = _layout->add(object_ptr<ListWidget>(
this,
_layout.get(),
_listController.get()));
const auto skip = _layout->add(object_ptr<Ui::RpWidget>(_layout.get()));
_mode.value(
) | rpl::start_with_next([=](PanelMode mode) {
skip->resize(skip->width(), (mode == PanelMode::Default)
? st::groupCallMembersBottomSkip
: 0);
}, skip->lifetime());
_layout->heightValue(
rpl::combine(
_mode.value(),
_layout->heightValue()
) | rpl::start_with_next([=] {
resizeToList();
}, _layout->lifetime());
@ -2030,7 +2048,7 @@ void Members::setupFakeRoundCorners() {
};
const auto create = [&](QPoint imagePartOrigin) {
const auto result = Ui::CreateChild<Ui::RpWidget>(this);
const auto result = Ui::CreateChild<Ui::RpWidget>(_layout.get());
result->show();
result->resize(size, size);
result->setAttribute(Qt::WA_TransparentForMouseEvents);
@ -2050,14 +2068,24 @@ void Members::setupFakeRoundCorners() {
const auto bottomleft = create({ 0, shift });
const auto bottomright = create({ shift, shift });
sizeValue(
) | rpl::start_with_next([=](QSize size) {
topleft->move(0, 0);
topright->move(size.width() - topright->width(), 0);
bottomleft->move(0, size.height() - bottomleft->height());
bottomright->move(
size.width() - bottomright->width(),
size.height() - bottomright->height());
rpl::combine(
_list->geometryValue(),
_addMemberButton.value() | rpl::map([=](Ui::RpWidget *widget) {
topleft->raise();
topright->raise();
bottomleft->raise();
bottomright->raise();
return widget ? widget->heightValue() : rpl::single(0);
}) | rpl::flatten_latest()
) | rpl::start_with_next([=](QRect list, int addMembers) {
const auto left = list.x();
const auto top = list.y() - addMembers;
const auto right = list.x() + list.width() - topright->width();
const auto bottom = list.y() + list.height() - bottomleft->height();
topleft->move(left, top);
topright->move(right, top);
bottomleft->move(left, bottom);
bottomright->move(right, bottom);
}, lifetime());
refreshImage();

View file

@ -58,6 +58,7 @@ public:
[[nodiscard]] MembersRow *lookupRow(not_null<PeerData*> peer) const;
void setMode(PanelMode mode);
[[nodiscard]] QRect getInnerGeometry() const;
private:
class Controller;

View file

@ -384,6 +384,16 @@ struct Panel::VideoTile {
VideoEndpoint endpoint;
};
struct Panel::ControlsBackgroundNarrow {
explicit ControlsBackgroundNarrow(not_null<QWidget*> parent)
: shadow(parent)
, blocker(parent) {
}
Ui::RpWidget shadow;
Ui::RpWidget blocker;
};
Panel::Panel(not_null<GroupCall*> call)
: _call(call)
, _peer(call->peer())
@ -697,6 +707,8 @@ void Panel::initControls() {
) | rpl::start_with_next([=](not_null<Data::GroupCall*> real) {
setupRealMuteButtonState(real);
}, _callLifetime);
refreshControlsBackground();
}
void Panel::refreshLeftButton() {
@ -799,7 +811,7 @@ void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
real->scheduleDateValue(),
real->scheduleStartSubscribedValue(),
Data::CanManageGroupCallValue(_peer),
_videoMode.value()
_mode.value()
) | rpl::distinct_until_changed(
) | rpl::filter(
_2 != GroupCall::InstanceState::TransitionToRtc
@ -809,7 +821,8 @@ void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
TimeId scheduleDate,
bool scheduleStartSubscribed,
bool canManage,
bool videoMode) {
PanelMode mode) {
const auto wide = (mode == PanelMode::Wide);
using Type = Ui::CallMuteButtonType;
_mute->setState(Ui::CallMuteButtonState{
.text = (scheduleDate
@ -821,19 +834,19 @@ void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
: state == GroupCall::InstanceState::Disconnected
? tr::lng_group_call_connecting(tr::now)
: mute == MuteState::ForceMuted
? (videoMode
? (wide
? tr::lng_group_call_force_muted_small(tr::now)
: tr::lng_group_call_force_muted(tr::now))
: mute == MuteState::RaisedHand
? (videoMode
? (wide
? tr::lng_group_call_raised_hand_small(tr::now)
: tr::lng_group_call_raised_hand(tr::now))
: mute == MuteState::Muted
? tr::lng_group_call_unmute(tr::now)
: (videoMode
: (wide
? tr::lng_group_call_you_are_live_small(tr::now)
: tr::lng_group_call_you_are_live(tr::now))),
.subtext = ((scheduleDate || videoMode)
.subtext = ((scheduleDate || wide)
? QString()
: state == GroupCall::InstanceState::Disconnected
? QString()
@ -930,6 +943,10 @@ void Panel::setupScheduledLabels(rpl::producer<TimeId> date) {
}, _startsWhen->lifetime());
}
PanelMode Panel::mode() const {
return _mode.current();
}
void Panel::setupMembers() {
if (_members) {
return;
@ -942,7 +959,7 @@ void Panel::setupMembers() {
_members.create(widget(), _call);
setupPinnedVideo();
_members->setMode(_mode);
_members->setMode(mode());
_members->show();
_members->desiredHeightValue(
@ -985,7 +1002,7 @@ void Panel::setupMembers() {
_call->videoEndpointPinnedValue(
) | rpl::start_with_next([=](const VideoEndpoint &pinned) {
if (_mode == PanelMode::Wide) {
if (mode() == PanelMode::Wide) {
refreshTilesGeometry();
} else if (pinned) {
enlargeVideo();
@ -1062,8 +1079,12 @@ void Panel::minimizeVideo() {
}
void Panel::raiseControls() {
if (_controlsBackground) {
_controlsBackground->raise();
if (_controlsBackgroundWide) {
_controlsBackgroundWide->raise();
}
if (_controlsBackgroundNarrow) {
_controlsBackgroundNarrow->shadow.raise();
_controlsBackgroundNarrow->blocker.raise();
}
const auto buttons = {
&_settings,
@ -1084,7 +1105,7 @@ void Panel::refreshTilesGeometry() {
const auto outer = _pinnedVideoWrap->size();
if (_videoTiles.empty()
|| outer.isEmpty()
|| _mode == PanelMode::Default) {
|| mode() == PanelMode::Default) {
return;
}
struct Geometry {
@ -1204,7 +1225,7 @@ void Panel::setupPinnedVideo() {
auto video = std::make_unique<LargeVideo>(
raw,
st::groupCallLargeVideoWide,
(_mode == PanelMode::Wide),
(mode() == PanelMode::Wide),
rpl::single(LargeVideoTrack{ track.track.get(), row }),
_call->videoEndpointPinnedValue() | rpl::map(_1 == endpoint));
@ -1781,7 +1802,7 @@ bool Panel::updateMode() {
const auto wide = _call->videoCall()
&& (widget()->width() >= st::groupCallWideModeWidthMin);
const auto mode = wide ? PanelMode::Wide : PanelMode::Default;
if (_mode == mode) {
if (_mode.current() == mode) {
return false;
}
_mode = mode;
@ -1813,15 +1834,120 @@ bool Panel::updateMode() {
}
void Panel::refreshControlsBackground() {
if (_mode != PanelMode::Wide) {
if (mode() == PanelMode::Default) {
trackControls(false);
_controlsBackground.destroy();
} else if (_controlsBackground) {
return;
_controlsBackgroundWide.destroy();
if (_controlsBackgroundNarrow) {
return;
}
setupControlsBackgroundNarrow();
} else {
_controlsBackgroundNarrow = nullptr;
if (_controlsBackgroundWide) {
return;
}
setupControlsBackgroundWide();
}
_controlsBackground.create(widget());
_controlsBackground->show();
auto &lifetime = _controlsBackground->lifetime();
raiseControls();
updateButtonsGeometry();
}
void Panel::setupControlsBackgroundNarrow() {
_controlsBackgroundNarrow = std::make_unique<ControlsBackgroundNarrow>(
widget());
_controlsBackgroundNarrow->shadow.show();
_controlsBackgroundNarrow->blocker.show();
auto &lifetime = _controlsBackgroundNarrow->shadow.lifetime();
const auto factor = cIntRetinaFactor();
const auto height = std::max(
st::groupCallMembersShadowHeight,
st::groupCallMembersFadeSkip + st::groupCallMembersFadeHeight);
const auto full = lifetime.make_state<QImage>(
QSize(1, height * factor),
QImage::Format_ARGB32_Premultiplied);
rpl::single(
rpl::empty_value()
) | rpl::then(
style::PaletteChanged()
) | rpl::start_with_next([=] {
full->fill(Qt::transparent);
auto p = QPainter(full);
const auto bottom = (height - st::groupCallMembersFadeSkip) * factor;
p.fillRect(
0,
bottom,
full->width(),
st::groupCallMembersFadeSkip * factor,
st::groupCallMembersBg);
p.drawImage(
QRect(
0,
bottom - (st::groupCallMembersFadeHeight * factor),
full->width(),
st::groupCallMembersFadeHeight * factor),
GenerateShadow(
st::groupCallMembersFadeHeight,
0,
255,
st::groupCallMembersBg->c));
p.drawImage(
QRect(
0,
(height - st::groupCallMembersShadowHeight) * factor,
full->width(),
st::groupCallMembersShadowHeight * factor),
GenerateShadow(
st::groupCallMembersShadowHeight,
0,
255,
st::groupCallBg->c));
}, lifetime);
_controlsBackgroundNarrow->shadow.resize(
(widget()->width()
- st::groupCallMembersMargin.left()
- st::groupCallMembersMargin.right()),
height);
_controlsBackgroundNarrow->shadow.paintRequest(
) | rpl::start_with_next([=](QRect clip) {
auto p = QPainter(&_controlsBackgroundNarrow->shadow);
clip = clip.intersected(_controlsBackgroundNarrow->shadow.rect());
const auto inner = _members->getInnerGeometry().translated(
_members->x() - _controlsBackgroundNarrow->shadow.x(),
_members->y() - _controlsBackgroundNarrow->shadow.y());
const auto faded = clip.intersected(inner);
if (!faded.isEmpty()) {
const auto factor = cIntRetinaFactor();
p.drawImage(
faded,
*full,
QRect(
0,
faded.y() * factor,
full->width(),
faded.height() * factor));
}
const auto bottom = inner.y() + inner.height();
const auto after = clip.intersected(QRect(
0,
bottom,
inner.width(),
_controlsBackgroundNarrow->shadow.height() - bottom));
if (!after.isEmpty()) {
p.fillRect(after, st::groupCallBg);
}
}, lifetime);
_controlsBackgroundNarrow->shadow.setAttribute(
Qt::WA_TransparentForMouseEvents);
_controlsBackgroundNarrow->blocker.setUpdatesEnabled(false);
}
void Panel::setupControlsBackgroundWide() {
_controlsBackgroundWide.create(widget());
_controlsBackgroundWide->show();
auto &lifetime = _controlsBackgroundWide->lifetime();
const auto color = lifetime.make_state<style::complex_color>([] {
auto result = st::groupCallBg->c;
result.setAlphaF(kControlsBackgroundOpacity);
@ -1830,14 +1956,13 @@ void Panel::refreshControlsBackground() {
const auto corners = lifetime.make_state<Ui::RoundRect>(
st::groupCallControlsBackRadius,
color->color());
_controlsBackground->paintRequest(
_controlsBackgroundWide->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(_controlsBackground.data());
corners->paint(p, _controlsBackground->rect());
auto p = QPainter(_controlsBackgroundWide.data());
corners->paint(p, _controlsBackgroundWide->rect());
}, lifetime);
trackControls(true);
raiseControls();
}
void Panel::trackControls(bool track) {
@ -1875,7 +2000,7 @@ void Panel::trackControls(bool track) {
trackOne(_settings);
trackOne(_callShare);
trackOne(_hangup);
trackOne(_controlsBackground);
trackOne(_controlsBackgroundWide);
}
void Panel::updateControlsGeometry() {
@ -1923,23 +2048,20 @@ void Panel::updateButtonsGeometry() {
toggleOne(_callShare);
toggleOne(_hangup);
};
if (_videoMode.current()) {
if (mode() == PanelMode::Wide) {
_mute->setStyle(st::callMuteButtonSmall);
const auto shown = _wideControlsAnimation.value(
_wideControlsShown ? 1. : 0.);
toggle(_mode != PanelMode::Wide || shown > 0.);
toggle(shown > 0.);
for (const auto &tile : _videoTiles) {
tile.video->setControlsShown(shown);
}
const auto buttonsTop = widget()->height()
- (_mode == PanelMode::Wide
? anim::interpolate(
0,
st::groupCallButtonBottomSkipWide,
shown)
: st::groupCallButtonBottomSkipSmall);
const auto buttonsTop = widget()->height() - anim::interpolate(
0,
st::groupCallButtonBottomSkipWide,
shown);
const auto addSkip = st::callMuteButtonSmall.active.outerRadius;
const auto muteSize = _mute->innerSize().width() + 2 * addSkip;
const auto skip = (_video ? 1 : 2) * st::groupCallButtonSkipSmall;
@ -1951,28 +2073,32 @@ void Panel::updateButtonsGeometry() {
const auto membersSkip = st::groupCallNarrowSkip;
const auto membersWidth = st::groupCallNarrowMembersWidth
+ 2 * membersSkip;
auto left = (_mode == PanelMode::Default)
? (widget()->width() - fullWidth) / 2
: ((widget()->width()
- membersWidth
- membersSkip
- fullWidth) / 2);
auto left = (widget()->width()
- membersWidth
- membersSkip
- fullWidth) / 2;
_mute->moveInner({ left + addSkip, buttonsTop + addSkip });
left += muteSize + skip;
if (_video) {
_video->setStyle(
st::groupCallVideoSmall,
&st::groupCallVideoActiveSmall);
_video->moveToLeft(left, buttonsTop);
left += _video->width() + skip;
}
if (_screenShare) {
_screenShare->setVisible(true);
_screenShare->moveToLeft(left, buttonsTop);
left += _video->width() + skip;
}
if (_settings) {
_settings->setVisible(true);
_settings->setStyle(st::groupCallSettingsSmall);
_settings->moveToLeft(left, buttonsTop);
left += _settings->width() + skip;
}
if (_callShare) {
_callShare->setVisible(true);
_callShare->setStyle(st::groupCallShareSmall);
_callShare->moveToLeft(left, buttonsTop);
left += _callShare->width() + skip;
@ -1980,13 +2106,13 @@ void Panel::updateButtonsGeometry() {
_hangup->setStyle(st::groupCallHangupSmall);
_hangup->moveToLeft(left, buttonsTop);
left += _hangup->width();
if (_controlsBackground) {
if (_controlsBackgroundWide) {
const auto rect = QRect(
left - fullWidth,
buttonsTop,
fullWidth,
_hangup->height());
_controlsBackground->setGeometry(
_controlsBackgroundWide->setGeometry(
rect.marginsAdded(st::groupCallControlsBackMargin));
}
} else {
@ -2003,17 +2129,46 @@ void Panel::updateButtonsGeometry() {
+ 2 * st::groupCallButtonSkip;
_mute->moveInner({ (widget()->width() - muteSize) / 2, muteTop });
const auto leftButtonLeft = (widget()->width() - fullWidth) / 2;
if (_screenShare) {
_screenShare->setVisible(false);
}
if (_video) {
_video->setStyle(st::groupCallVideo, &st::groupCallVideoActive);
_video->moveToLeft(leftButtonLeft, buttonsTop);
}
if (_settings) {
_settings->setVisible(!_video);
_settings->setStyle(st::groupCallSettings);
_settings->moveToLeft(leftButtonLeft, buttonsTop);
}
if (_callShare) {
_callShare->setVisible(!_video);
_callShare->setStyle(st::groupCallShare);
_callShare->moveToLeft(leftButtonLeft, buttonsTop);
}
_hangup->setStyle(st::groupCallHangup);
_hangup->moveToRight(leftButtonLeft, buttonsTop);
}
if (_controlsBackgroundNarrow) {
const auto left = st::groupCallMembersMargin.left();
const auto width = (widget()->width()
- st::groupCallMembersMargin.left()
- st::groupCallMembersMargin.right());
_controlsBackgroundNarrow->shadow.setGeometry(
left,
(widget()->height()
- st::groupCallMembersMargin.bottom()
- _controlsBackgroundNarrow->shadow.height()),
width,
_controlsBackgroundNarrow->shadow.height());
_controlsBackgroundNarrow->blocker.setGeometry(
left,
(widget()->height()
- st::groupCallMembersMargin.bottom()
- st::groupCallMembersBottomSkip),
width,
st::groupCallMembersBottomSkip);
}
}
void Panel::updateMembersGeometry() {
@ -2021,7 +2176,7 @@ void Panel::updateMembersGeometry() {
return;
}
const auto desiredHeight = _members->desiredHeight();
if (_mode == PanelMode::Wide) {
if (mode() == PanelMode::Wide) {
const auto skip = st::groupCallNarrowSkip;
const auto membersWidth = st::groupCallNarrowMembersWidth;
const auto top = st::groupCallWideVideoTop;
@ -2036,9 +2191,7 @@ void Panel::updateMembersGeometry() {
widget()->width() - membersWidth - 3 * skip,
widget()->height() - top - skip);
} else {
const auto membersBottom = _videoMode.current()
? (widget()->height() - st::groupCallMembersBottomSkipSmall)
: (widget()->height() - st::groupCallMuteBottomSkip);
const auto membersBottom = widget()->height();
const auto membersTop = st::groupCallMembersTop;
const auto availableHeight = membersBottom
- st::groupCallMembersMargin.bottom()
@ -2086,7 +2239,7 @@ void Panel::refreshTitle() {
_title->setAttribute(Qt::WA_TransparentForMouseEvents);
}
refreshTitleGeometry();
if (!_subtitle && _mode == PanelMode::Default) {
if (!_subtitle && mode() == PanelMode::Default) {
_subtitle.create(
widget(),
rpl::single(
@ -2141,7 +2294,7 @@ void Panel::refreshTitleGeometry() {
: fullRect;
const auto best = _title->naturalWidth();
const auto from = (widget()->width() - best) / 2;
const auto top = (_mode == PanelMode::Default)
const auto top = (mode() == PanelMode::Default)
? st::groupCallTitleTop
: (st::groupCallWideVideoTop
- st::groupCallTitleLabel.style.font->height) / 2;

View file

@ -71,9 +71,12 @@ public:
private:
using State = GroupCall::State;
struct VideoTile;
struct ControlsBackgroundNarrow;
[[nodiscard]] not_null<Ui::RpWidget*> widget() const;
[[nodiscard]] PanelMode mode() const;
void paint(QRect clip);
void initWindow();
@ -102,6 +105,8 @@ private:
void updateButtonsGeometry();
void updateMembersGeometry();
void refreshControlsBackground();
void setupControlsBackgroundWide();
void setupControlsBackgroundNarrow();
void showControls();
void refreshLeftButton();
void refreshTilesGeometry();
@ -134,7 +139,7 @@ private:
const std::unique_ptr<Ui::Window> _window;
const std::unique_ptr<Ui::LayerManager> _layerBg;
PanelMode _mode = PanelMode();
rpl::variable<PanelMode> _mode;
#ifndef Q_OS_MAC
std::unique_ptr<Ui::Platform::TitleControls> _controls;
@ -167,7 +172,8 @@ private:
bool _wideControlsShown = false;
Ui::Animations::Simple _wideControlsAnimation;
object_ptr<Ui::RpWidget> _controlsBackground = { nullptr };
object_ptr<Ui::RpWidget> _controlsBackgroundWide = { nullptr };
std::unique_ptr<ControlsBackgroundNarrow> _controlsBackgroundNarrow;
object_ptr<Ui::CallButton> _settings = { nullptr };
object_ptr<Ui::CallButton> _callShare = { nullptr };
object_ptr<Ui::CallButton> _video = { nullptr };