From dcc14a47266fda8ea5bef1b164313cdc150febe4 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 18 Oct 2021 19:53:28 +0400 Subject: [PATCH] Add info rows to PeerShortInfoBox. --- .../boxes/peers/peer_short_info_box.cpp | 149 +++++++++++++++++- .../boxes/peers/peer_short_info_box.h | 13 ++ .../boxes/peers/prepare_short_info_box.cpp | 3 +- .../calls/group/calls_group_panel.cpp | 5 +- .../calls/group/calls_group_viewport.cpp | 47 ------ .../group/calls_group_viewport_raster.cpp | 6 +- Telegram/SourceFiles/info/info.style | 15 +- 7 files changed, 185 insertions(+), 53 deletions(-) diff --git a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp index 89c254758..dc696a4fc 100644 --- a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp @@ -8,7 +8,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peers/peer_short_info_box.h" #include "ui/widgets/labels.h" +#include "ui/widgets/scroll_area.h" +#include "ui/wrap/vertical_layout.h" +#include "ui/wrap/slide_wrap.h" +#include "ui/wrap/wrap.h" #include "ui/image/image_prepare.h" +#include "ui/text/text_utilities.h" +#include "info/profile/info_profile_text.h" #include "media/streaming/media_streaming_instance.h" #include "media/streaming/media_streaming_player.h" #include "lang/lang_keys.h" @@ -17,6 +23,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace { +constexpr auto kShadowMaxAlpha = 80; + } // namespace PeerShortInfoBox::PeerShortInfoBox( @@ -30,6 +38,14 @@ PeerShortInfoBox::PeerShortInfoBox( , _fields(std::move(fields)) , _name(this, nameValue(), st::shortInfoName) , _status(this, std::move(status), st::shortInfoStatus) +, _scroll(this, st::defaultSolidScroll) +, _rows( + static_cast( + _scroll->setOwnedWidget( + object_ptr( + _scroll.data(), + object_ptr( + _scroll.data())))->entity())) , _videoPaused(std::move(videoPaused)) { std::move( userpic @@ -54,8 +70,80 @@ void PeerShortInfoBox::prepare() { ? tr::lng_view_button_group() : tr::lng_profile_view_channel(), [=] { _openRequests.fire({}); }); + prepareRows(); + setNoContentMargin(true); - setDimensions(st::shortInfoWidth, st::shortInfoWidth); + + _rows->move(0, 0); + _rows->heightValue( + ) | rpl::start_with_next([=](int height) { + setDimensions(st::shortInfoWidth, st::shortInfoWidth + height); + }, lifetime()); +} + +void PeerShortInfoBox::prepareRows() { + using namespace Info::Profile; + + auto addInfoLineGeneric = [&]( + rpl::producer &&label, + rpl::producer &&text, + const style::FlatLabel &textSt = st::infoLabeled) { + auto line = CreateTextWithLabel( + _rows, + rpl::duplicate(label) | Ui::Text::ToWithEntities(), + rpl::duplicate(text), + textSt, + st::shortInfoLabeledPadding); + _rows->add(std::move(line.wrap)); + + rpl::combine( + std::move(label), + std::move(text) + ) | rpl::start_with_next([=] { + _rows->resizeToWidth(st::shortInfoWidth); + }, _rows->lifetime()); + + //line.text->setClickHandlerFilter(infoClickFilter); + return line.text; + }; + auto addInfoLine = [&]( + rpl::producer &&label, + rpl::producer &&text, + const style::FlatLabel &textSt = st::infoLabeled) { + return addInfoLineGeneric( + std::move(label), + std::move(text), + textSt); + }; + auto addInfoOneLine = [&]( + rpl::producer &&label, + rpl::producer &&text, + const QString &contextCopyText) { + auto result = addInfoLine( + std::move(label), + std::move(text), + st::infoLabeledOneLine); + result->setDoubleClickSelectsParagraph(true); + result->setContextCopyText(contextCopyText); + return result; + }; + addInfoOneLine( + tr::lng_info_link_label(), + linkValue(), + tr::lng_context_copy_link(tr::now)); + addInfoOneLine( + tr::lng_info_mobile_label(), + phoneValue() | Ui::Text::ToWithEntities(), + tr::lng_profile_copy_phone(tr::now)); + auto label = _fields.current().isBio + ? tr::lng_info_bio_label() + : tr::lng_info_about_label(); + addInfoLine(std::move(label), aboutValue()); + addInfoOneLine( + tr::lng_info_username_label(), + usernameValue() | Ui::Text::ToWithEntities(), + tr::lng_context_copy_mention(tr::now)); + } RectParts PeerShortInfoBox::customCornersFilling() { @@ -64,6 +152,20 @@ RectParts PeerShortInfoBox::customCornersFilling() { void PeerShortInfoBox::resizeEvent(QResizeEvent *e) { BoxContent::resizeEvent(e); + + _name->moveToLeft( + st::shortInfoNamePosition.x(), + st::shortInfoWidth - st::shortInfoNamePosition.y() - _name->height(), + width()); + _status->moveToLeft( + st::shortInfoStatusPosition.x(), + (st::shortInfoWidth + - st::shortInfoStatusPosition.y() + - _status->height()), + height()); + _rows->resizeToWidth(st::shortInfoWidth); + _scroll->resize(st::shortInfoWidth, height() - st::shortInfoWidth); + _scroll->move(0, st::shortInfoWidth); } void PeerShortInfoBox::paintEvent(QPaintEvent *e) { @@ -89,6 +191,27 @@ void PeerShortInfoBox::paintEvent(QPaintEvent *e) { if (_videoInstance && _videoInstance->ready() && !paused) { _videoInstance->markFrameShown(); } + + if (_shadow.isNull()) { + _shadow = Images::GenerateShadow( + st::shortInfoShadowHeight, + 0, + kShadowMaxAlpha); + } + const auto shadowRect = QRect( + 0, + st::shortInfoWidth - st::shortInfoShadowHeight, + st::shortInfoWidth, + st::shortInfoShadowHeight); + const auto factor = style::DevicePixelRatio(); + p.drawImage( + shadowRect, + _shadow, + QRect( + 0, + 0, + _shadow.width(), + st::shortInfoShadowHeight * factor)); } QImage PeerShortInfoBox::currentVideoFrame() const { @@ -113,6 +236,30 @@ rpl::producer PeerShortInfoBox::nameValue() const { }) | rpl::distinct_until_changed(); } +rpl::producer PeerShortInfoBox::linkValue() const { + return _fields.value() | rpl::map([](const PeerShortInfoFields &fields) { + return Ui::Text::Link(fields.link, fields.link); + }) | rpl::distinct_until_changed(); +} + +rpl::producer PeerShortInfoBox::phoneValue() const { + return _fields.value() | rpl::map([](const PeerShortInfoFields &fields) { + return fields.phone; + }) | rpl::distinct_until_changed(); +} + +rpl::producer PeerShortInfoBox::usernameValue() const { + return _fields.value() | rpl::map([](const PeerShortInfoFields &fields) { + return fields.username; + }) | rpl::distinct_until_changed(); +} + +rpl::producer PeerShortInfoBox::aboutValue() const { + return _fields.value() | rpl::map([](const PeerShortInfoFields &fields) { + return fields.about; + }) | rpl::distinct_until_changed(); +} + void PeerShortInfoBox::applyUserpic(PeerShortInfoUserpic &&value) { if (!value.photo.isNull() && _userpicImage.cacheKey() != value.photo.cacheKey()) { diff --git a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h index e6d7f11d2..06e701f0e 100644 --- a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h +++ b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h @@ -17,6 +17,10 @@ enum class Error; struct Information; } // namespace Media::Streaming +namespace Ui { +class VerticalLayout; +} // namespace Ui + enum class PeerShortInfoType { User, Group, @@ -29,6 +33,7 @@ struct PeerShortInfoFields { QString link; TextWithEntities about; QString username; + bool isBio = false; }; struct PeerShortInfoUserpic { @@ -56,6 +61,7 @@ public: private: void prepare() override; + void prepareRows(); RectParts customCornersFilling() override; void resizeEvent(QResizeEvent *e) override; @@ -64,6 +70,10 @@ private: [[nodiscard]] QImage currentVideoFrame() const; [[nodiscard]] rpl::producer nameValue() const; + [[nodiscard]] rpl::producer linkValue() const; + [[nodiscard]] rpl::producer phoneValue() const; + [[nodiscard]] rpl::producer usernameValue() const; + [[nodiscard]] rpl::producer aboutValue() const; void applyUserpic(PeerShortInfoUserpic &&value); QRect coverRect() const; QRect radialRect() const; @@ -80,11 +90,14 @@ private: object_ptr _name; object_ptr _status; + object_ptr _scroll; + not_null _rows; QImage _userpicImage; std::unique_ptr _videoInstance; crl::time _videoStartPosition = 0; Fn _videoPaused; + QImage _shadow; rpl::event_stream<> _openRequests; diff --git a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp index 284935188..865d230d0 100644 --- a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp @@ -162,7 +162,8 @@ void ProcessFullPhoto( .about = Info::Profile::AboutWithEntities(peer, peer->about()), .username = ((user && !username.isEmpty()) ? ('@' + username) - : QString()) + : QString()), + .isBio = (user && !user->isBot()), }; }); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index c33dbeb64..870d0c6df 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/toast/toast.h" #include "ui/toasts/common_toasts.h" +#include "ui/image/image_prepare.h" #include "ui/round_rect.h" #include "ui/special_buttons.h" #include "info/profile/info_profile_values.h" // Info::Profile::Value. @@ -1549,7 +1550,7 @@ void Panel::setupControlsBackgroundNarrow() { bottom - (st::groupCallMembersFadeHeight * factor), full->width(), st::groupCallMembersFadeHeight * factor), - GenerateShadow( + Images::GenerateShadow( st::groupCallMembersFadeHeight, 0, 255, @@ -1560,7 +1561,7 @@ void Panel::setupControlsBackgroundNarrow() { (height - st::groupCallMembersShadowHeight) * factor, full->width(), st::groupCallMembersShadowHeight * factor), - GenerateShadow( + Images::GenerateShadow( st::groupCallMembersShadowHeight, 0, 255, diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp b/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp index 5fe4dcd5e..5fdcc7edc 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp @@ -847,53 +847,6 @@ rpl::lifetime &Viewport::lifetime() { return _content->lifetime(); } -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()), - (premultiplied - ? QImage::Format_ARGB32_Premultiplied - : QImage::Format_ARGB32)); - if (topAlpha == bottomAlpha) { - color.setAlpha(topAlpha); - result.fill(color); - return result; - } - constexpr auto kShift = 16; - constexpr auto kMultiply = (1U << kShift); - const auto values = std::abs(topAlpha - bottomAlpha); - const auto rows = uint32(result.height()); - const auto step = (values * kMultiply) / (rows - 1); - const auto till = rows * uint32(step); - Assert(result.bytesPerLine() == sizeof(uint32)); - auto ints = reinterpret_cast(result.bits()); - if (topAlpha < bottomAlpha) { - for (auto i = uint32(0); i != till; i += step) { - *ints++ = base | ((topAlpha + (i >> kShift)) << 24); - } - } else { - for (auto i = uint32(0); i != till; i += step) { - *ints++ = base | ((topAlpha - (i >> kShift)) << 24); - } - } - if (!premultiplied) { - result = std::move(result).convertToFormat( - QImage::Format_ARGB32_Premultiplied); - } - return result; -} - rpl::producer MuteButtonTooltip(not_null call) { //return rpl::single(std::make_tuple( // (Data::GroupCall*)nullptr, diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport_raster.cpp b/Telegram/SourceFiles/calls/group/calls_group_viewport_raster.cpp index 335db764e..3add8cc63 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport_raster.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport_raster.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_peer.h" #include "media/view/media_view_pip.h" #include "webrtc/webrtc_video_track.h" +#include "ui/image/image_prepare.h" #include "lang/lang_keys.h" #include "styles/style_calls.h" #include "styles/palette.h" @@ -277,7 +278,10 @@ void Viewport::RendererSW::paintTileControls( // Shadow. if (_shadow.isNull()) { - _shadow = GenerateShadow(st.shadowHeight, 0, kShadowMaxAlpha); + _shadow = Images::GenerateShadow( + st.shadowHeight, + 0, + kShadowMaxAlpha); } const auto shadowRect = QRect( x, diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index d7f66c957..ba072ce5e 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -954,7 +954,20 @@ infoScrollDateHideTimeout: historyScrollDateHideTimeout; infoDateFadeDuration: historyDateFadeDuration; shortInfoName: FlatLabel(defaultFlatLabel) { + textFg: groupCallVideoTextFg; + maxHeight: 19px; + style: TextStyle(defaultTextStyle) { + font: font(15px semibold); + linkFont: font(15px semibold); + linkFontOver: font(15px semibold underline); + } } shortInfoStatus: FlatLabel(defaultFlatLabel) { + textFg: groupCallVideoSubTextFg; + maxHeight: 18px; } -shortInfoWidth: 336px; +shortInfoWidth: 304px; +shortInfoNamePosition: point(25px, 37px); +shortInfoStatusPosition: point(25px, 14px); +shortInfoShadowHeight: 80px; +shortInfoLabeledPadding: margins(20px, 16px, 20px, 0px);