From 7b0513a1ea5eac7f4de6126a01d86c0504467b11 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 7 Feb 2022 18:35:32 +0300 Subject: [PATCH] Improve box rounding and buttons. --- .../SourceFiles/boxes/add_contact_box.cpp | 2 +- Telegram/SourceFiles/boxes/boxes.style | 4 +-- .../boxes/peers/peer_short_info_box.cpp | 35 ++++++++++++------- .../boxes/peers/peer_short_info_box.h | 3 ++ .../boxes/peers/prepare_short_info_box.cpp | 35 ++++++++++++------- .../boxes/peers/prepare_short_info_box.h | 7 +++- Telegram/SourceFiles/boxes/send_files_box.cpp | 2 +- Telegram/SourceFiles/calls/calls.style | 1 + .../calls/group/calls_group_members.cpp | 4 ++- Telegram/SourceFiles/info/info.style | 28 ++++++++------- Telegram/lib_ui | 2 +- 11 files changed, 78 insertions(+), 45 deletions(-) diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp index a376ee9c31..c63d744200 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp @@ -1381,7 +1381,7 @@ void EditNameBox::prepare() { newHeight += st::contactSkip + _last->height(); newHeight += st::boxPadding.bottom() + st::contactPadding.bottom(); - setDimensions(st::boxWideWidth, newHeight); + setDimensions(st::boxWidth, newHeight); addButton(tr::lng_settings_save(), [=] { save(); }); addButton(tr::lng_cancel(), [=] { closeBox(); }); diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 55c5e4975f..a3ad673578 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -139,8 +139,8 @@ contactUserIcon: icon {{ "settings/settings_name", menuIconFg }}; contactPhoneIcon: icon {{ "settings/settings_phone_number", menuIconFg }}; contactIconPosition: point(-5px, 23px); -contactPadding: margins(49px, 2px, 0px, 12px); -contactSkip: 6px; +contactPadding: margins(49px, 2px, 0px, 14px); +contactSkip: 9px; contactPhoneSkip: 30px; contactsPhotoSize: 42px; diff --git a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp index 9077837bf9..806be1f00e 100644 --- a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp @@ -93,6 +93,7 @@ PeerShortInfoCover::PeerShortInfoCover( , _name(_widget.get(), std::move(name), _nameStyle->st) , _statusStyle(std::make_unique(_st.status)) , _status(_widget.get(), std::move(status), _statusStyle->st) +, _roundMask(Images::CornersMask(_st.radius)) , _videoPaused(std::move(videoPaused)) { _widget->setCursor(_cursor); @@ -145,7 +146,7 @@ PeerShortInfoCover::PeerShortInfoCover( _st.size); _roundedTopImage = QImage( - QSize(_st.size, st::boxRadius) * style::DevicePixelRatio(), + QSize(_st.size, _st.radius) * style::DevicePixelRatio(), QImage::Format_ARGB32_Premultiplied); _roundedTopImage.setDevicePixelRatio(style::DevicePixelRatio()); _roundedTopImage.fill(Qt::transparent); @@ -161,6 +162,10 @@ object_ptr PeerShortInfoCover::takeOwned() { return std::move(_owned); } +gsl::span PeerShortInfoCover::roundMask() const { + return _roundMask; +} + void PeerShortInfoCover::setScrollTop(int scrollTop) { _scrollTop = scrollTop; _widget->update(); @@ -176,16 +181,21 @@ rpl::lifetime &PeerShortInfoCover::lifetime() { void PeerShortInfoCover::paint(QPainter &p) { checkStreamedIsStarted(); - const auto frame = currentVideoFrame(); + auto frame = currentVideoFrame(); auto paused = _videoPaused && _videoPaused(); - if (frame.isNull() && _userpicImage.isNull()) { + if (!frame.isNull()) { + frame = Images::Round( + std::move(frame), + _roundMask, + RectPart::TopLeft | RectPart::TopRight); + } else if (_userpicImage.isNull()) { auto image = QImage( _widget->size() * style::DevicePixelRatio(), QImage::Format_ARGB32_Premultiplied); image.fill(Qt::black); _userpicImage = Images::Round( std::move(image), - ImageRoundRadius::Small, + _roundMask, RectPart::TopLeft | RectPart::TopRight); } @@ -200,7 +210,7 @@ void PeerShortInfoCover::paint(QPainter &p) { void PeerShortInfoCover::paintCoverImage(QPainter &p, const QImage &image) { const auto roundedWidth = _st.size; - const auto roundedHeight = st::boxRadius; + const auto roundedHeight = _st.radius; const auto covered = (_st.size - _scrollTop); if (covered <= 0) { return; @@ -230,7 +240,7 @@ void PeerShortInfoCover::paintCoverImage(QPainter &p, const QImage &image) { q.end(); _roundedTopImage = Images::Round( std::move(_roundedTopImage), - ImageRoundRadius::Small, + _roundMask, RectPart::TopLeft | RectPart::TopRight); p.drawImage( QRect(0, from, roundedWidth, rounded), @@ -245,7 +255,7 @@ void PeerShortInfoCover::paintBars(QPainter &p) { _shadowTop = Images::GenerateShadow(height, kShadowMaxAlpha, 0); _shadowTop = Images::Round( _shadowTop.scaled(QSize(_st.size, height) * factor), - ImageRoundRadius::Small, + _roundMask, RectPart::TopLeft | RectPart::TopRight); } const auto shadowRect = QRect(0, _scrollTop, _st.size, height); @@ -395,8 +405,6 @@ QImage PeerShortInfoCover::currentVideoFrame() const { const auto request = Media::Streaming::FrameRequest{ .resize = size * style::DevicePixelRatio(), .outer = size, - .radius = ImageRoundRadius::Small, - .corners = RectPart::TopLeft | RectPart::TopRight, }; return (_videoInstance && _videoInstance->player().ready() @@ -420,9 +428,12 @@ void PeerShortInfoCover::applyUserpic(PeerShortInfoUserpic &&value) { const auto videoChanged = _videoInstance ? (_videoInstance->shared() != value.videoDocument) : (value.videoDocument != nullptr); - const auto frame = videoChanged ? currentVideoFrame() : QImage(); + auto frame = videoChanged ? currentVideoFrame() : QImage(); if (!frame.isNull()) { - _userpicImage = frame; + _userpicImage = Images::Round( + std::move(frame), + _roundMask, + RectPart::TopLeft | RectPart::TopRight); } } else if (_userpicImage.cacheKey() != value.photo.cacheKey()) { _userpicImage = std::move(value.photo); @@ -771,7 +782,7 @@ void PeerShortInfoBox::refreshRoundedTopImage(const QColor &color) { _roundedTop.fill(color); _roundedTop = Images::Round( std::move(_roundedTop), - ImageRoundRadius::Small, + _cover.roundMask(), RectPart::TopLeft | RectPart::TopRight); } diff --git a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h index 021ad97976..fc29b7062d 100644 --- a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h +++ b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h @@ -65,6 +65,8 @@ public: [[nodiscard]] not_null widget() const; [[nodiscard]] object_ptr takeOwned(); + [[nodiscard]] gsl::span roundMask() const; + void setScrollTop(int scrollTop); [[nodiscard]] rpl::producer moveRequests() const; @@ -106,6 +108,7 @@ private: std::unique_ptr _statusStyle; object_ptr _status; + std::array _roundMask; QImage _userpicImage; QImage _roundedTopImage; QImage _barSmall; diff --git a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp index e996b72bdc..5ca433f792 100644 --- a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp @@ -41,6 +41,8 @@ struct UserpicState { std::vector> photoPreloads; InMemoryKey userpicKey; PhotoId photoId = PeerData::kUnknownPhotoId; + std::array roundMask; + int size = 0; bool waitingFull = false; bool waitingLoad = false; }; @@ -50,16 +52,16 @@ void GenerateImage( QImage image, bool blurred = false) { using namespace Images; - const auto size = st::shortInfoWidth; + const auto size = state->size; const auto ratio = style::DevicePixelRatio(); - const auto options = Option::RoundSmall - | Option::RoundSkipBottomLeft - | Option::RoundSkipBottomRight - | (blurred ? Option::Blur : Option()); - state->current.photo = Images::Prepare( - std::move(image), - QSize(size, size) * ratio, - { .options = options, .outer = { size, size } }); + const auto options = blurred ? Option::Blur : Option(); + state->current.photo = Images::Round( + Images::Prepare( + std::move(image), + QSize(size, size) * ratio, + { .options = options, .outer = { size, size } }), + state->roundMask, + RectPart::TopLeft | RectPart::TopRight); } void GenerateImage( @@ -350,14 +352,19 @@ bool ProcessCurrent( } [[nodiscard]] PreparedShortInfoUserpic UserpicValue( - not_null peer) { + not_null peer, + const style::ShortInfoCover &st) { const auto moveRequests = std::make_shared>(); auto move = [=](int shift) { moveRequests->fire_copy(shift); }; + const auto size = st.size; + const auto radius = st.radius; auto value = [=](auto consumer) { auto lifetime = rpl::lifetime(); const auto state = lifetime.make_state(); + state->size = size; + state->roundMask = Images::CornersMask(radius); const auto push = [=](bool force = false) { if (ProcessCurrent(peer, state) || force) { consumer.put_next_copy(state->current); @@ -421,7 +428,7 @@ object_ptr PrepareShortInfoBox( : peer->isBroadcast() ? PeerShortInfoType::Channel : PeerShortInfoType::Group; - auto userpic = UserpicValue(peer); + auto userpic = UserpicValue(peer, st::shortInfoCover); auto result = Box( type, FieldsValue(peer), @@ -456,6 +463,8 @@ rpl::producer PrepareShortInfoStatus(not_null peer) { return StatusValue(peer); } -PreparedShortInfoUserpic PrepareShortInfoUserpic(not_null peer) { - return UserpicValue(peer); +PreparedShortInfoUserpic PrepareShortInfoUserpic( + not_null peer, + const style::ShortInfoCover &st) { + return UserpicValue(peer, st); } diff --git a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h index 18b7fa3c09..3572c21380 100644 --- a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h +++ b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h @@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class PeerData; +namespace style { +struct ShortInfoCover; +} // namespace style + namespace Ui { class BoxContent; } // namespace Ui @@ -39,4 +43,5 @@ struct PreparedShortInfoUserpic { not_null peer); [[nodiscard]] PreparedShortInfoUserpic PrepareShortInfoUserpic( - not_null peer); + not_null peer, + const style::ShortInfoCover &st); diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index b85eb88d41..dd90bcfb29 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -916,7 +916,7 @@ void SendFilesBox::paintEvent(QPaintEvent *e) { p.setPen(st::boxTitleFg); p.drawTextLeft( st::boxPhotoTitlePosition.x(), - st::boxTitlePosition.y(), + st::boxTitlePosition.y() - st::boxTopMargin, width(), _titleText); } diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index 189646d7d9..722cff04f0 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -553,6 +553,7 @@ groupCallPopupMenuWithCover: PopupMenu(groupCallPopupMenu) { } } groupCallMenuCover: ShortInfoCover(shortInfoCover) { + radius: roundRadiusSmall; size: groupCallMenuCoverSize; namePosition: point(17px, 28px); statusPosition: point(17px, 8px); diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.cpp b/Telegram/SourceFiles/calls/group/calls_group_members.cpp index 7f4cfbfe2b..a2c95febe2 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members.cpp @@ -1263,7 +1263,9 @@ base::unique_qptr Members::Controller::createRowContextMenu( participantPeer ) | rpl::map([](const auto &text) { return text.text; }), PrepareShortInfoStatus(participantPeer), - PrepareShortInfoUserpic(participantPeer))); + PrepareShortInfoUserpic( + participantPeer, + st::groupCallMenuCover))); if (const auto about = participantPeer->about(); !about.isEmpty()) { result->addAction(base::make_unique_q( diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 7d5bb99f4e..d808e51ff5 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -199,40 +199,40 @@ infoLayerTopBarBack: IconButton(infoTopBarBack) { width: infoLayerTopBarHeight; height: infoLayerTopBarHeight; - iconPosition: point(12px, -1px); + iconPosition: point(10px, -1px); icon: infoLayerTopBarBackIcon; iconOver: infoLayerTopBarBackIconOver; - rippleAreaSize: 44px; + rippleAreaSize: 40px; + rippleAreaPosition: point(6px, 4px); } infoLayerTopBarMediaCancel: IconButton(infoLayerTopBarBack) { icon: icon {{ "info_close", boxTitleCloseFg }}; iconOver: icon {{ "info_close", boxTitleCloseFgOver }}; } infoLayerTopBarClose: IconButton(infoLayerTopBarMediaCancel) { - width: 50px; - iconPosition: point(6px, -1px); - rippleAreaPosition: point(0px, 6px); + iconPosition: point(4px, -1px); + rippleAreaPosition: point(0px, 4px); } infoLayerTopBarMenu: IconButton(infoLayerTopBarClose) { - width: 44px; + width: 40px; icon: icon {{ "title_menu_dots", boxTitleCloseFg }}; iconOver: icon {{ "title_menu_dots", boxTitleCloseFgOver }}; - iconPosition: point(18px, -1px); + iconPosition: point(16px, -1px); } infoLayerTopBarNotifications: IconButton(infoLayerTopBarMenu) { icon: icon {{ "info_notifications", boxTitleCloseFg }}; iconOver: icon {{ "info_notifications", boxTitleCloseFgOver }}; - iconPosition: point(5px, 11px); + iconPosition: point(3px, 9px); } infoLayerTopBarCall: IconButton(infoLayerTopBarMenu) { icon: icon {{ "top_bar_call", boxTitleCloseFg }}; iconOver: icon {{ "top_bar_call", boxTitleCloseFgOver }}; - iconPosition: point(5px, -1px); + iconPosition: point(3px, -1px); } infoLayerTopBarSave: IconButton(infoLayerTopBarNotifications) { icon: icon {{ "passport_ready", windowActiveTextFg }}; iconOver: icon {{ "passport_ready", windowActiveTextFg }}; - iconPosition: point(13px, 18px); + iconPosition: point(11px, 16px); ripple: RippleAnimation(defaultRippleAnimation) { color: lightButtonBgOver; } @@ -242,7 +242,7 @@ infoLayerTopBarForward: IconButton(infoLayerTopBarBack) { icon: icon {{ "info_media_forward", boxTitleCloseFg }}; iconOver: icon {{ "info_media_forward", boxTitleCloseFgOver }}; iconPosition: point(11px, -1px); - rippleAreaPosition: point(1px, 6px); + rippleAreaPosition: point(3px, 4px); } infoLayerTopBarDelete: IconButton(infoLayerTopBarForward) { icon: icon {{ "info_media_delete", boxTitleCloseFg }}; @@ -252,7 +252,7 @@ infoLayerTopBar: InfoTopBar(infoTopBar) { height: infoLayerTopBarHeight; back: infoLayerTopBarBack; title: boxTitle; - titlePosition: boxTitlePosition; + titlePosition: point(24px, 13px); bg: boxBg; mediaCancel: infoLayerTopBarMediaCancel; mediaActionsSkip: 6px; @@ -955,7 +955,7 @@ infoScrollDateHideTimeout: historyScrollDateHideTimeout; infoDateFadeDuration: historyDateFadeDuration; shortInfoWidth: 304px; -shortInfoLabeledPadding: margins(20px, 16px, 20px, 0px); +shortInfoLabeledPadding: margins(24px, 16px, 24px, 0px); shortInfoScroll: ScrollArea(defaultScrollArea) { deltat: 3px; deltab: 0px; @@ -969,6 +969,7 @@ shortInfoScroll: ScrollArea(defaultScrollArea) { ShortInfoCover { size: pixels; + radius: pixels; name: FlatLabel; namePosition: point; status: FlatLabel; @@ -981,6 +982,7 @@ ShortInfoCover { } shortInfoCover: ShortInfoCover { size: shortInfoWidth; + radius: boxRadius; name: FlatLabel(defaultFlatLabel) { textFg: groupCallVideoTextFg; maxHeight: 19px; diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 7e1effeeeb..681da392eb 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 7e1effeeebfc411fbdf0370754dc7d9735f33805 +Subproject commit 681da392eb0523e87f9c1e9b3c732757e0c18850