From 00ce302b381e031da2a9f7fe208ab35c44db736d Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 6 May 2021 19:57:40 +0400 Subject: [PATCH] Improve narrow participants column design. --- Telegram/Resources/langs/lang.strings | 6 +- Telegram/SourceFiles/calls/calls.style | 18 +- .../calls/group/calls_group_call.cpp | 49 +++-- .../calls/group/calls_group_call.h | 13 +- .../calls/group/calls_group_members.cpp | 168 +++++++++++++----- .../calls/group/calls_group_members.h | 2 +- .../calls/group/calls_group_panel.cpp | 48 +++-- .../SourceFiles/settings/settings_common.cpp | 68 ++++--- .../SourceFiles/settings/settings_common.h | 9 +- Telegram/ThirdParty/tgcalls | 2 +- Telegram/lib_rpl | 2 +- Telegram/lib_ui | 2 +- 12 files changed, 271 insertions(+), 116 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 4cf23232f4..581c36a0dd 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2069,8 +2069,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_call_context_remove_hand" = "Cancel request to speak"; "lng_group_call_context_mute_for_me" = "Mute for me"; "lng_group_call_context_unmute_for_me" = "Unmute for me"; -"lng_group_call_context_pin_video" = "Pin video"; -"lng_group_call_context_unpin_video" = "Unpin video"; +"lng_group_call_context_pin_camera" = "Pin video"; +"lng_group_call_context_unpin_camera" = "Unpin video"; +"lng_group_call_context_pin_screen" = "Pin screencast"; +"lng_group_call_context_unpin_screen" = "Unpin screencast"; "lng_group_call_context_remove" = "Remove"; "lng_group_call_remove_channel" = "Remove {channel} from the voice chat?"; "lng_group_call_duration_days#one" = "{count} day"; diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index afc113e1ae..0344576f4e 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -811,9 +811,6 @@ groupCallHangupSmall: CallButton(groupCallHangup) { groupCallVideoSmallInner: IconButton(groupCallSettingsInner) { icon: icon {{ "calls/call_camera_muted", groupCallIconFg }}; iconPosition: point(-1px, 16px); - ripple: RippleAnimation(defaultRippleAnimation) { - color: groupCallLeaveBgRipple; - } height: 76px; } groupCallVideoSmall: CallButton(groupCallShareSmall) { @@ -1136,6 +1133,19 @@ desktopCaptureSubmit: RoundButton(desktopCaptureCancel) { groupCallNarrowSkip: 9px; groupCallNarrowRowSkip: 8px; -groupCallNarrowSize: size(90px, 90px); +groupCallNarrowSize: size(144px, 90px); groupCallWideModeWidthMin: 520px; groupCallWideModeSize: size(720px, 480px); +groupCallNarrowAddMemberHeight: 32px; + +groupCallNarrowAddMember: RoundButton(defaultActiveButton) { + textFg: groupCallMemberNotJoinedStatus; + textFgOver: groupCallMemberNotJoinedStatus; + textBg: groupCallMembersBg; + textBgOver: groupCallMembersBgOver; + + height: 32px; + radius: roundRadiusLarge; + + ripple: groupCallRipple; +} diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index 773ccc7bf4..21bf245e8e 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -388,6 +388,10 @@ GroupCall::GroupCall( , _joinHash(info.joinHash) , _id(inputCall.c_inputGroupCall().vid().v) , _scheduleDate(info.scheduleDate) +, _cameraOutgoing(std::make_unique( + Webrtc::VideoState::Inactive)) +, _screenOutgoing(std::make_unique( + Webrtc::VideoState::Inactive)) , _lastSpokeCheckTimer([=] { checkLastSpoke(); }) , _checkJoinedTimer([=] { checkJoined(); }) , _pushToTalkCancelTimer([=] { pushToTalkCancel(); }) @@ -460,8 +464,15 @@ GroupCall::~GroupCall() { } bool GroupCall::isSharingScreen() const { - return _screenOutgoing - && (_screenOutgoing->state() == Webrtc::VideoState::Active); + return (_screenOutgoing->state() == Webrtc::VideoState::Active); +} + +rpl::producer GroupCall::isSharingScreenValue() const { + using namespace rpl::mappers; + return _screenOutgoing->stateValue( + ) | rpl::map( + _1 == Webrtc::VideoState::Active + ) | rpl::distinct_until_changed(); } const std::string &GroupCall::screenSharingEndpoint() const { @@ -469,8 +480,15 @@ const std::string &GroupCall::screenSharingEndpoint() const { } bool GroupCall::isSharingCamera() const { - return _cameraOutgoing - && (_cameraOutgoing->state() == Webrtc::VideoState::Active); + return (_cameraOutgoing->state() == Webrtc::VideoState::Active); +} + +rpl::producer GroupCall::isSharingCameraValue() const { + using namespace rpl::mappers; + return _cameraOutgoing->stateValue( + ) | rpl::map( + _1 == Webrtc::VideoState::Active + ) | rpl::distinct_until_changed(); } const std::string &GroupCall::cameraSharingEndpoint() const { @@ -611,7 +629,7 @@ void GroupCall::subscribeToReal(not_null real) { const auto wasSounding = data.was && data.was->sounding; if (nowSpeaking == wasSpeaking && nowSounding == wasSounding) { return; - } else if (!_videoEndpointPinned.empty()) { + } else if (!_videoEndpointPinned.current().empty()) { return; } if (nowScreenEndpoint != newLarge @@ -876,7 +894,7 @@ void GroupCall::setMyEndpointType( } const auto nowLarge = activeVideoEndpointType( _videoEndpointLarge.current()); - if (_videoEndpointPinned.empty() + if (_videoEndpointPinned.current().empty() && ((type == EndpointType::Screen && nowLarge != EndpointType::Screen) || (type == EndpointType::Camera @@ -1604,14 +1622,10 @@ void GroupCall::setupMediaDevices() { void GroupCall::ensureOutgoingVideo() { Expects(_id != 0); - if (_cameraOutgoing) { + if (_videoInited) { return; } - - _cameraOutgoing = std::make_unique( - Webrtc::VideoState::Inactive); - _screenOutgoing = std::make_unique( - Webrtc::VideoState::Inactive); + _videoInited = true; //static const auto hasDevices = [] { // return !Webrtc::GetVideoInputList().empty(); @@ -2057,7 +2071,7 @@ void GroupCall::setIncomingVideoEndpoints( feedOne(cameraSharingEndpoint()); feedOne(screenSharingEndpoint()); if (!newLarge.empty() && !newLargeFound) { - newLarge = _videoEndpointPinned = std::string(); + _videoEndpointPinned = newLarge = std::string(); } if (newLarge.empty()) { _videoEndpointLarge = chooseLargeVideoEndpoint(); @@ -2105,7 +2119,7 @@ void GroupCall::fillActiveVideoEndpoints() { feedOne(cameraSharingEndpoint(), EndpointType::Camera); feedOne(screenSharingEndpoint(), EndpointType::Screen); if (!newLarge.empty() && !newLargeFound) { - newLarge = _videoEndpointPinned = std::string(); + _videoEndpointPinned = newLarge = std::string(); } if (newLarge.empty()) { _videoEndpointLarge = chooseLargeVideoEndpoint(); @@ -2453,8 +2467,7 @@ void GroupCall::sendSelfUpdate(SendUpdateType type) { MTP_bool(muted() != MuteState::Active), MTP_int(100000), // volume MTP_bool(muted() == MuteState::RaisedHand), - MTP_bool(!_cameraOutgoing - || _cameraOutgoing->state() != Webrtc::VideoState::Active) + MTP_bool(_cameraOutgoing->state() != Webrtc::VideoState::Active) )).done([=](const MTPUpdates &result) { _updateMuteRequestId = 0; _peer->session().api().applyUpdates(result); @@ -2472,7 +2485,9 @@ void GroupCall::pinVideoEndpoint(const std::string &endpoint) { if (endpoint.empty()) { _videoEndpointPinned = endpoint; } else if (streamsVideo(endpoint)) { - _videoEndpointLarge = _videoEndpointPinned = endpoint; + _videoEndpointPinned = std::string(); + _videoEndpointLarge = endpoint; + _videoEndpointPinned = endpoint; } } diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index 7c5e916e0f..bbdfc07e15 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -235,10 +235,13 @@ public: && activeVideoEndpointType(endpoint) != EndpointType::None; } [[nodiscard]] const std::string &videoEndpointPinned() const { - return _videoEndpointPinned; + return _videoEndpointPinned.current(); + } + [[nodiscard]] rpl::producer videoEndpointPinnedValue() const { + return _videoEndpointPinned.value(); } void pinVideoEndpoint(const std::string &endpoint); - [[nodiscard]] std::string videoEndpointLarge() const { + [[nodiscard]] const std::string &videoEndpointLarge() const { return _videoEndpointLarge.current(); } [[nodiscard]] auto videoEndpointLargeValue() const @@ -266,8 +269,10 @@ public: void setCurrentAudioDevice(bool input, const QString &deviceId); void setCurrentVideoDevice(const QString &deviceId); [[nodiscard]] bool isSharingScreen() const; + [[nodiscard]] rpl::producer isSharingScreenValue() const; [[nodiscard]] const std::string &screenSharingEndpoint() const; [[nodiscard]] bool isSharingCamera() const; + [[nodiscard]] rpl::producer isSharingCameraValue() const; [[nodiscard]] const std::string &cameraSharingEndpoint() const; [[nodiscard]] QString screenSharingDeviceId() const; void toggleVideo(bool active); @@ -462,12 +467,14 @@ private: std::unique_ptr _screenOutgoing; QString _screenDeviceId; + bool _videoInited = false; + rpl::event_stream _levelUpdates; rpl::event_stream _streamsVideoUpdated; base::flat_set _incomingVideoEndpoints; base::flat_map _activeVideoEndpoints; rpl::variable _videoEndpointLarge; - std::string _videoEndpointPinned; + rpl::variable _videoEndpointPinned; std::unique_ptr _videoLargeTrackWrap; rpl::variable _videoLargeTrack; base::flat_map _lastSpoke; diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.cpp b/Telegram/SourceFiles/calls/group/calls_group_members.cpp index 2a8f7487a3..ec6796224f 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members.cpp @@ -185,7 +185,8 @@ public: int x, int y, int outerWidth, - int size, + int sizew, + int sizeh, PanelMode mode, bool selected = false); @@ -256,19 +257,32 @@ private: void ensureUserpicCache( std::shared_ptr &view, int size); - bool paintVideo(Painter &p, int x, int y, int size, PanelMode mode); + bool paintVideo( + Painter &p, + int x, + int y, + int sizew, + int sizeh, + PanelMode mode); [[nodiscard]] static std::tuple UserpicInWideMode( int x, int y, - int size); - void paintBlobs(Painter &p, int x, int y, int size, PanelMode mode); + int sizew, + int sizeh); + void paintBlobs( + Painter &p, + int x, + int y, + int sizew, + int sizeh, PanelMode mode); void paintScaledUserpic( Painter &p, std::shared_ptr &userpic, int x, int y, int outerWidth, - int size, + int sizew, + int sizeh, PanelMode mode); const not_null _delegate; @@ -694,7 +708,13 @@ void Row::ensureUserpicCache( } } -bool Row::paintVideo(Painter &p, int x, int y, int size, PanelMode mode) { +bool Row::paintVideo( + Painter &p, + int x, + int y, + int sizew, + int sizeh, + PanelMode mode) { if (!_videoTrackShown) { return false; } @@ -706,12 +726,14 @@ bool Row::paintVideo(Painter &p, int x, int y, int size, PanelMode mode) { || _videoTrackShown->state() != Webrtc::VideoState::Active) { return false; } - const auto resize = (videoSize.width() > videoSize.height()) - ? QSize(videoSize.width() * size / videoSize.height(), size) - : QSize(size, videoSize.height() * size / videoSize.width()); + const auto videow = videoSize.width(); + const auto videoh = videoSize.height(); + const auto resize = (videow * sizeh > videoh * sizew) + ? QSize(videow * sizeh / videoh, sizeh) + : QSize(sizew, videoh * sizew / videow); const auto request = Webrtc::FrameRequest{ .resize = resize * cIntRetinaFactor(), - .outer = QSize(size, size) * cIntRetinaFactor(), + .outer = QSize(sizew, sizeh) * cIntRetinaFactor(), }; const auto frame = _videoTrackShown->frame(request); auto copy = frame; // #TODO calls optimize. @@ -727,18 +749,30 @@ bool Row::paintVideo(Painter &p, int x, int y, int size, PanelMode mode) { return true; } -std::tuple Row::UserpicInWideMode(int x, int y, int size) { +std::tuple Row::UserpicInWideMode( + int x, + int y, + int sizew, + int sizeh) { const auto useSize = st::groupCallMembersList.item.photoSize; - const auto skip = (size - useSize) / 2; - return { x + skip, y + skip, useSize }; + const auto skipx = (sizew - useSize) / 2; + const auto skipy = (sizeh - useSize) / 2; + return { x + skipx, y + skipy, useSize }; } -void Row::paintBlobs(Painter &p, int x, int y, int size, PanelMode mode) { +void Row::paintBlobs( + Painter &p, + int x, + int y, + int sizew, + int sizeh, + PanelMode mode) { if (!_blobsAnimation) { return; } + auto size = sizew; if (mode == PanelMode::Wide) { - std::tie(x, y, size) = UserpicInWideMode(x, y, size); + std::tie(x, y, size) = UserpicInWideMode(x, y, sizew, sizeh); } const auto mutedByMe = (_state == State::MutedByMe); const auto shift = QPointF(x + size / 2., y + size / 2.); @@ -761,10 +795,12 @@ void Row::paintScaledUserpic( int x, int y, int outerWidth, - int size, + int sizew, + int sizeh, PanelMode mode) { + auto size = sizew; if (mode == PanelMode::Wide) { - std::tie(x, y, size) = UserpicInWideMode(x, y, size); + std::tie(x, y, size) = UserpicInWideMode(x, y, sizew, sizeh); } if (!_blobsAnimation) { peer()->paintUserpicLeft(p, userpic, x, y, outerWidth, size); @@ -800,7 +836,8 @@ void Row::paintScaledUserpic( auto Row::generatePaintUserpicCallback() -> PaintRoundImageCallback { return [=](Painter &p, int x, int y, int outerWidth, int size) { - paintComplexUserpic(p, x, y, outerWidth, size, PanelMode::Default); + const auto outer = outerWidth; + paintComplexUserpic(p, x, y, outer, size, size, PanelMode::Default); }; } @@ -809,18 +846,20 @@ void Row::paintComplexUserpic( int x, int y, int outerWidth, - int size, + int sizew, + int sizeh, PanelMode mode, bool selected) { if (mode == PanelMode::Wide) { - if (paintVideo(p, x, y, size, mode)) { + if (paintVideo(p, x, y, sizew, sizeh, mode)) { return; } _delegate->rowPaintWideBackground(p, selected); paintRipple(p, x, y, outerWidth); } - paintBlobs(p, x, y, size, mode); - if (mode == PanelMode::Default && paintVideo(p, x, y, size, mode)) { + paintBlobs(p, x, y, sizew, sizeh, mode); + if (mode == PanelMode::Default + && paintVideo(p, x, y, sizew, sizeh, mode)) { return; } paintScaledUserpic( @@ -829,7 +868,8 @@ void Row::paintComplexUserpic( x, y, outerWidth, - size, + sizew, + sizeh, mode); } @@ -1826,7 +1866,7 @@ void MembersController::rowPaintIcon( void MembersController::rowPaintWideBackground(Painter &p, bool selected) { (selected ? _wideRoundRectSelected : _wideRoundRect).paint( p, - { QPoint(), st::groupCallNarrowSize }); + { QPoint(st::groupCallNarrowSkip, 0), st::groupCallNarrowSize }); } int MembersController::customRowHeight() { @@ -1840,12 +1880,14 @@ void MembersController::customRowPaint( bool selected) { const auto real = static_cast(row.get()); const auto width = st::groupCallNarrowSize.width(); + const auto height = st::groupCallNarrowSize.height(); real->paintComplexUserpic( p, - 0, + st::groupCallNarrowSkip, 0, width, width, + height, PanelMode::Wide, selected); } @@ -1854,7 +1896,9 @@ bool MembersController::customRowSelectionPoint( not_null row, int x, int y) { - return y < st::groupCallNarrowSize.height(); + return x >= st::groupCallNarrowSkip + && x < st::groupCallNarrowSkip + st::groupCallNarrowSize.width() + && y < st::groupCallNarrowSize.height(); } Fn MembersController::customRowRippleMaskGenerator() { @@ -1973,7 +2017,7 @@ base::unique_qptr MembersController::createRowContextMenu( const auto participant = real->participantByEndpoint(pinnedEndpoint); if (participant && participant->peer == participantPeer) { result->addAction( - tr::lng_group_call_context_unpin_video(tr::now), + tr::lng_group_call_context_unpin_camera(tr::now), [=] { _call->pinVideoEndpoint(std::string()); }); } else { const auto &participants = real->participants(); @@ -1992,7 +2036,7 @@ base::unique_qptr MembersController::createRowContextMenu( : camera); }; result->addAction( - tr::lng_group_call_context_pin_video(tr::now), + tr::lng_group_call_context_pin_camera(tr::now), callback); } } @@ -2292,27 +2336,61 @@ void Members::setupAddMember(not_null call) { }); } - _canAddMembers.value( - ) | rpl::start_with_next([=](bool can) { + rpl::combine( + _canAddMembers.value(), + _mode.value() + ) | rpl::start_with_next([=](bool can, PanelMode mode) { + const auto old = _addMemberButton.current(); + delete old; if (!can) { - delete _addMemberButton.current(); - _addMemberButton = nullptr; - updateControlsGeometry(); - return; - } else if (_addMemberButton.current()) { + if (old) { + _addMemberButton = nullptr; + updateControlsGeometry(); + } return; } - auto addMember = Settings::CreateButton( - this, - tr::lng_group_call_invite(), - st::groupCallAddMember, - &st::groupCallAddMemberIcon, - st::groupCallAddMemberIconLeft); + auto addMember = (Ui::AbstractButton*)nullptr; + auto wrap = [&]() -> object_ptr { + if (mode == PanelMode::Default) { + auto result = Settings::CreateButton( + this, + tr::lng_group_call_invite(), + st::groupCallAddMember, + &st::groupCallAddMemberIcon, + st::groupCallAddMemberIconLeft, + &st::groupCallMemberInactiveIcon); + addMember = result.data(); + return result; + } + auto result = object_ptr(_layout.get()); + const auto skip = st::groupCallNarrowSkip; + const auto fullwidth = st::groupCallNarrowSize.width() + + 2 * skip; + const auto fullheight = st::groupCallNarrowAddMember.height + + st::groupCallNarrowRowSkip; + result->resize(fullwidth, fullheight); + const auto button = Ui::CreateChild( + result.data(), + rpl::single(QString()), + st::groupCallNarrowAddMember); + button->move(skip, 0); + const auto width = fullwidth - 2 * skip; + button->setFullWidth(width); + Settings::AddButtonIcon( + button, + &st::groupCallAddMemberIcon, + (width - st::groupCallAddMemberIcon.width()) / 2, + &st::groupCallMemberInactiveIcon); + addMember = button; + return result; + }(); addMember->show(); - addMember->addClickHandler([=] { // TODO throttle(ripple duration) - _addMemberRequests.fire({}); - }); - _addMemberButton = _layout->insert(1, std::move(addMember)); + addMember->clicks( + ) | rpl::to_empty | rpl::start_to_stream( + _addMemberRequests, + addMember->lifetime()); + _addMemberButton = wrap.data(); + _layout->insert(1, std::move(wrap)); }, lifetime()); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.h b/Telegram/SourceFiles/calls/group/calls_group_members.h index 3383536ccc..5c43d8cf8b 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.h +++ b/Telegram/SourceFiles/calls/group/calls_group_members.h @@ -87,7 +87,7 @@ private: std::unique_ptr _listController; not_null _layout; const not_null _pinnedVideo; - rpl::variable _addMemberButton = nullptr; + rpl::variable _addMemberButton = nullptr; ListWidget *_list = nullptr; rpl::event_stream<> _addMemberRequests; diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index 3a4cdb5b05..4a15bce3e9 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -65,6 +65,7 @@ constexpr auto kRecordingAnimationDuration = crl::time(1200); constexpr auto kRecordingOpacity = 0.6; constexpr auto kStartNoConfirmation = TimeId(10); constexpr auto kControlsBackgroundOpacity = 0.8; +constexpr auto kOverrideActiveColorBgAlpha = 236; class InviteController final : public ParticipantsBoxController { public: @@ -713,8 +714,21 @@ void Panel::refreshLeftButton() { } const auto raw = _callShare ? _callShare.data() : _settings.data(); raw->show(); - raw->setColorOverrides(_mute->colorOverrides()); + auto overrides = _mute->colorOverrides(); + raw->setColorOverrides(rpl::duplicate(overrides)); + + auto toggleableOverrides = [&](rpl::producer active) { + return rpl::combine( + std::move(active), + rpl::duplicate(overrides) + ) | rpl::map([](bool active, Ui::CallButtonColors colors) { + if (active && colors.bg) { + colors.bg->setAlpha(kOverrideActiveColorBgAlpha); + } + return colors; + }); + }; if (!_video) { _video.create( widget(), @@ -725,7 +739,12 @@ void Panel::refreshLeftButton() { _call->toggleVideo(!_call->isSharingCamera()); }); _video->setText(tr::lng_group_call_video()); - _video->setColorOverrides(_mute->colorOverrides()); + _video->setColorOverrides( + toggleableOverrides(_call->isSharingCameraValue())); + _call->isSharingCameraValue( + ) | rpl::start_with_next([=](bool sharing) { + _video->setProgress(sharing ? 1. : 0.); + }, _video->lifetime()); } if (!_screenShare) { _screenShare.create(widget(), st::groupCallScreenShareSmall); @@ -736,7 +755,12 @@ void Panel::refreshLeftButton() { #endif // Q_OS_LINUX }); _screenShare->setText(tr::lng_group_call_screen_share()); - _screenShare->setColorOverrides(_mute->colorOverrides()); + _screenShare->setColorOverrides( + toggleableOverrides(_call->isSharingScreenValue())); + _call->isSharingScreenValue( + ) | rpl::start_with_next([=](bool sharing) { + _screenShare->setProgress(sharing ? 1. : 0.); + }, _screenShare->lifetime()); } } @@ -1687,19 +1711,19 @@ void Panel::updateMembersGeometry() { } const auto desiredHeight = _members->desiredHeight(); if (_mode == PanelMode::Wide) { + const auto skip = st::groupCallNarrowSkip; + const auto membersWidth = st::groupCallNarrowSize.width() + 2 * skip; + const auto top = st::groupCallWideVideoTop; _members->setGeometry( - st::groupCallNarrowSkip, 0, - st::groupCallNarrowSize.width(), + top, + membersWidth, std::min(desiredHeight, widget()->height())); - const auto pinnedLeft = st::groupCallNarrowSkip * 2 - + st::groupCallNarrowSize.width(); - const auto pinnedTop = st::groupCallWideVideoTop; _pinnedVideo->setGeometry( - pinnedLeft, - pinnedTop, - widget()->width() - pinnedLeft - st::groupCallNarrowSkip, - widget()->height() - pinnedTop - st::groupCallNarrowSkip); + membersWidth, + top, + widget()->width() - membersWidth - skip, + widget()->height() - top - skip); } else { const auto membersBottom = _videoMode.current() ? (widget()->height() - st::groupCallMembersBottomSkipSmall) diff --git a/Telegram/SourceFiles/settings/settings_common.cpp b/Telegram/SourceFiles/settings/settings_common.cpp index f94456ee6d..7b9e48c558 100644 --- a/Telegram/SourceFiles/settings/settings_common.cpp +++ b/Telegram/SourceFiles/settings/settings_common.cpp @@ -35,9 +35,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Settings { object_ptr
CreateSection( - Type type, - not_null parent, - not_null controller) { + Type type, + not_null parent, + not_null controller) { switch (type) { case Type::Main: return object_ptr
(parent, controller); @@ -74,8 +74,8 @@ void AddDivider(not_null container) { } void AddDividerText( - not_null container, - rpl::producer text) { + not_null container, + rpl::producer text) { container->add(object_ptr( container, object_ptr( @@ -85,37 +85,49 @@ void AddDividerText( st::settingsDividerLabelPadding)); } +not_null AddButtonIcon( + not_null button, + const style::icon *leftIcon, + int iconLeft, + const style::color *leftIconOver) { + const auto icon = Ui::CreateChild(button.get()); + icon->setAttribute(Qt::WA_TransparentForMouseEvents); + icon->resize(leftIcon->size()); + button->sizeValue( + ) | rpl::start_with_next([=](QSize size) { + icon->moveToLeft( + iconLeft ? iconLeft : st::settingsSectionIconLeft, + (size.height() - icon->height()) / 2, + size.width()); + }, icon->lifetime()); + icon->paintRequest( + ) | rpl::start_with_next([=] { + Painter p(icon); + const auto width = icon->width(); + const auto paintOver = (button->isOver() || button->isDown()) + && !button->isDisabled(); + if (!paintOver) { + leftIcon->paint(p, QPoint(), width); + } else if (leftIconOver) { + leftIcon->paint(p, QPoint(), width, (*leftIconOver)->c); + } else { + leftIcon->paint(p, QPoint(), width, st::menuIconFgOver->c); + } + }, icon->lifetime()); + return icon; +} + object_ptr