diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index bac31208c..abbed88a5 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -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; diff --git a/Telegram/SourceFiles/calls/group/calls_group_large_video.cpp b/Telegram/SourceFiles/calls/group/calls_group_large_video.cpp index 6f3d1fa94..f8a044903 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_large_video.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_large_video.cpp @@ -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(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; } diff --git a/Telegram/SourceFiles/calls/group/calls_group_large_video.h b/Telegram/SourceFiles/calls/group/calls_group_large_video.h index 48c51d457..f8dde4500 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_large_video.h +++ b/Telegram/SourceFiles/calls/group/calls_group_large_video.h @@ -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 diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.cpp b/Telegram/SourceFiles/calls/group/calls_group_members.cpp index 40b8dcbd1..b14c5e630 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members.cpp @@ -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 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 Members::fullCountValue() const { return _listController->fullCountValue(); } @@ -1817,10 +1826,19 @@ rpl::producer Members::fullCountValue() const { void Members::setupList() { _listController->setStyleOverrides(&st::groupCallMembersList); _list = _layout->add(object_ptr( - this, + _layout.get(), _listController.get())); + const auto skip = _layout->add(object_ptr(_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(this); + const auto result = Ui::CreateChild(_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(); diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.h b/Telegram/SourceFiles/calls/group/calls_group_members.h index e1dc3c163..167a87856 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.h +++ b/Telegram/SourceFiles/calls/group/calls_group_members.h @@ -58,6 +58,7 @@ public: [[nodiscard]] MembersRow *lookupRow(not_null peer) const; void setMode(PanelMode mode); + [[nodiscard]] QRect getInnerGeometry() const; private: class Controller; diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index ce995e385..904d63572 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -384,6 +384,16 @@ struct Panel::VideoTile { VideoEndpoint endpoint; }; +struct Panel::ControlsBackgroundNarrow { + explicit ControlsBackgroundNarrow(not_null parent) + : shadow(parent) + , blocker(parent) { + } + + Ui::RpWidget shadow; + Ui::RpWidget blocker; +}; + Panel::Panel(not_null call) : _call(call) , _peer(call->peer()) @@ -697,6 +707,8 @@ void Panel::initControls() { ) | rpl::start_with_next([=](not_null real) { setupRealMuteButtonState(real); }, _callLifetime); + + refreshControlsBackground(); } void Panel::refreshLeftButton() { @@ -799,7 +811,7 @@ void Panel::setupRealMuteButtonState(not_null 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 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 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 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( 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( + 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( + 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([] { auto result = st::groupCallBg->c; result.setAlphaF(kControlsBackgroundOpacity); @@ -1830,14 +1956,13 @@ void Panel::refreshControlsBackground() { const auto corners = lifetime.make_state( 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; diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.h b/Telegram/SourceFiles/calls/group/calls_group_panel.h index f3efbb88d..03e57e27a 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.h +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.h @@ -71,9 +71,12 @@ public: private: using State = GroupCall::State; struct VideoTile; + struct ControlsBackgroundNarrow; [[nodiscard]] not_null 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 _window; const std::unique_ptr _layerBg; - PanelMode _mode = PanelMode(); + rpl::variable _mode; #ifndef Q_OS_MAC std::unique_ptr _controls; @@ -167,7 +172,8 @@ private: bool _wideControlsShown = false; Ui::Animations::Simple _wideControlsAnimation; - object_ptr _controlsBackground = { nullptr }; + object_ptr _controlsBackgroundWide = { nullptr }; + std::unique_ptr _controlsBackgroundNarrow; object_ptr _settings = { nullptr }; object_ptr _callShare = { nullptr }; object_ptr _video = { nullptr };