From f94fd3118bafd91719ba1bfc9c391e82900d939c Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 12 Dec 2024 12:11:39 +0400 Subject: [PATCH] Add "My Profile" instead of "My Stories". --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/info/info.style | 17 +- .../SourceFiles/info/info_wrap_widget.cpp | 12 ++ .../info/profile/info_profile_actions.cpp | 64 +++++-- .../info/profile/info_profile_actions.h | 15 ++ .../profile/info_profile_inner_widget.cpp | 31 +-- .../stories/info_stories_inner_widget.cpp | 178 +++++++++++++++--- .../info/stories/info_stories_inner_widget.h | 8 + .../info/stories/info_stories_widget.cpp | 4 + .../SourceFiles/settings/settings_main.cpp | 2 +- .../SourceFiles/window/window_main_menu.cpp | 50 ++--- 11 files changed, 273 insertions(+), 109 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 47bd1c965..2a2b05514 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_menu_activate" = "Use this account"; "lng_menu_set_status" = "Set Emoji Status"; "lng_menu_change_status" = "Change Emoji Status"; +"lng_menu_my_profile" = "My Profile"; "lng_menu_my_stories" = "My Stories"; "lng_menu_my_groups" = "My Groups"; "lng_menu_my_channels" = "My Channels"; diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 4302f7a30..d034bb3df 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -168,10 +168,17 @@ infoTopBarCall: IconButton(infoTopBarMenu) { rippleAreaPosition: point(0px, 6px); } infoTopBarQr: IconButton(infoTopBarMenu) { - width: 52px; + width: 48px; icon: icon {{ "menu/qr_code", boxTitleCloseFg }}; iconOver: icon {{ "menu/qr_code", boxTitleCloseFgOver }}; - iconPosition: point(9px, -1px); + iconPosition: point(8px, -1px); + rippleAreaPosition: point(0px, 6px); +} +infoTopBarEdit: IconButton(infoTopBarMenu) { + width: 48px; + icon: icon {{ "menu/edit", boxTitleCloseFg }}; + iconOver: icon {{ "menu/edit", boxTitleCloseFgOver }}; + iconPosition: point(8px, -1px); rippleAreaPosition: point(0px, 6px); } infoTopBarForward: IconButton(infoTopBarBack) { @@ -273,6 +280,12 @@ infoLayerTopBarQr: IconButton(infoLayerTopBarClose) { iconOver: icon {{ "menu/qr_code", boxTitleCloseFgOver }}; iconPosition: point(8px, -1px); } +infoLayerTopBarEdit: IconButton(infoLayerTopBarClose) { + width: 40px; + icon: icon {{ "menu/edit", boxTitleCloseFg }}; + iconOver: icon {{ "menu/edit", boxTitleCloseFgOver }}; + iconPosition: point(8px, -1px); +} infoLayerTopBarForward: IconButton(infoLayerTopBarBack) { width: 45px; icon: icon {{ "info/info_media_forward", boxTitleCloseFg }}; diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 2c4f06482..fbfb691ca 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -382,6 +382,7 @@ void WrapWidget::setupTopBarMenuToggle() { if (!_topBar) { return; } + const auto key = _controller->key(); const auto section = _controller->section(); if (section.type() == Section::Type::Profile && (wrap() != Wrap::Side || hasStackHistory())) { @@ -406,6 +407,17 @@ void WrapWidget::setupTopBarMenuToggle() { }); } } + } else if (key.storiesPeer() + && key.storiesPeer()->isSelf() + && key.storiesTab() == Stories::Tab::Saved) { + const auto &st = (wrap() == Wrap::Layer) + ? st::infoLayerTopBarEdit + : st::infoTopBarEdit; + const auto button = _topBar->addButton( + base::make_unique_q(_topBar, st)); + button->addClickHandler([=] { + _controller->showSettings(::Settings::Information::Id()); + }); } else if (section.type() == Section::Type::Downloads) { auto &manager = Core::App().downloadManager(); rpl::merge( diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 068b29c3b..ff9eb7707 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -50,6 +50,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/channel_statistics/earn/earn_format.h" #include "info/channel_statistics/earn/earn_icons.h" #include "info/channel_statistics/earn/info_channel_earn_list.h" +#include "info/profile/info_profile_cover.h" #include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_phone_menu.h" #include "info/profile/info_profile_text.h" @@ -1240,9 +1241,9 @@ object_ptr DetailsFiller::setupInfo() { int rightSkip) { const auto parent = label->parentWidget(); rpl::combine( - label->geometryValue(), + result->widthValue(), button->sizeValue() - ) | rpl::start_with_next([=](const QRect &, const QSize &buttonSize) { + ) | rpl::start_with_next([=](int, QSize buttonSize) { const auto s = parent->size(); button->moveToRight( rightSkip, @@ -2010,6 +2011,9 @@ Ui::MultiSlideTracker DetailsFiller::fillUserButtons( using namespace rpl::mappers; Ui::MultiSlideTracker tracker; + if (user->isSelf()) { + return tracker; + } auto window = _controller->parentController(); auto addSendMessageButton = [&] { @@ -2034,24 +2038,7 @@ Ui::MultiSlideTracker DetailsFiller::fillUserButtons( tracker); }; - if (user->isSelf()) { - auto separator = _wrap->add(object_ptr>( - _wrap, - object_ptr(_wrap), - st::infoProfileSeparatorPadding) - )->setDuration( - st::infoSlideDuration - ); - - addSendMessageButton(); - - separator->toggleOn( - std::move(tracker).atLeastOneShownValue() - ); - } else { - addSendMessageButton(); - } - + addSendMessageButton(); addReportReaction(tracker); return tracker; @@ -2722,5 +2709,42 @@ object_ptr SetupChannelMembersAndManage( return result; } +Cover *AddCover( + not_null container, + not_null controller, + not_null peer, + Data::ForumTopic *topic) { + const auto result = topic + ? container->add(object_ptr( + container, + controller->parentController(), + topic)) + : container->add(object_ptr( + container, + controller->parentController(), + peer)); + result->showSection( + ) | rpl::start_with_next([=](Section section) { + controller->showSection(topic + ? std::make_shared(topic, section) + : std::make_shared(peer, section)); + }, result->lifetime()); + result->setOnlineCount(rpl::single(0)); + return result; +} + +void AddDetails( + not_null container, + not_null controller, + not_null peer, + Data::ForumTopic *topic, + Origin origin) { + if (topic) { + container->add(SetupDetails(controller, container, topic)); + } else { + container->add(SetupDetails(controller, container, peer, origin)); + } +} + } // namespace Profile } // namespace Info diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.h b/Telegram/SourceFiles/info/profile/info_profile_actions.h index c6b070a85..078ce0720 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.h +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.h @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui { class RpWidget; +class VerticalLayout; } // namespace Ui namespace Data { @@ -25,6 +26,7 @@ namespace Info::Profile { extern const char kOptionShowPeerIdBelowAbout[]; +class Cover; struct Origin; object_ptr SetupDetails( @@ -48,4 +50,17 @@ object_ptr SetupChannelMembersAndManage( not_null parent, not_null peer); +Cover *AddCover( + not_null container, + not_null controller, + not_null peer, + Data::ForumTopic *topic); +void AddDetails( + not_null container, + not_null controller, + not_null peer, + Data::ForumTopic *topic, + Origin origin); + } // namespace Info::Profile + diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp index 5a9a81942..e0e72cdca 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp @@ -70,7 +70,6 @@ InnerWidget::InnerWidget( object_ptr InnerWidget::setupContent( not_null parent, Origin origin) { - auto result = object_ptr(parent); if (const auto user = _peer->asUser()) { user->session().changes().peerFlagsValue( user, @@ -85,30 +84,14 @@ object_ptr InnerWidget::setupContent( } }, lifetime()); } - _cover = _topic - ? result->add(object_ptr( - result, - _controller->parentController(), - _topic)) - : result->add(object_ptr( - result, - _controller->parentController(), - _peer)); - _cover->showSection( - ) | rpl::start_with_next([=](Section section) { - _controller->showSection(_topic - ? std::make_shared(_topic, section) - : std::make_shared(_peer, section)); - }, _cover->lifetime()); - _cover->setOnlineCount(rpl::single(0)); - if (_topic) { - if (_topic->creating()) { - return result; - } - result->add(SetupDetails(_controller, parent, _topic)); - } else { - result->add(SetupDetails(_controller, parent, _peer, origin)); + + auto result = object_ptr(parent); + _cover = AddCover(result, _controller, _peer, _topic); + if (_topic && _topic->creating()) { + return result; } + + AddDetails(result, _controller, _peer, _topic, origin); result->add(setupSharedMedia(result.data())); if (_topic) { return result; diff --git a/Telegram/SourceFiles/info/stories/info_stories_inner_widget.cpp b/Telegram/SourceFiles/info/stories/info_stories_inner_widget.cpp index bfabe89c2..c83795cab 100644 --- a/Telegram/SourceFiles/info/stories/info_stories_inner_widget.cpp +++ b/Telegram/SourceFiles/info/stories/info_stories_inner_widget.cpp @@ -13,8 +13,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "dialogs/ui/dialogs_stories_content.h" #include "dialogs/ui/dialogs_stories_list.h" +#include "info/media/info_media_buttons.h" #include "info/media/info_media_list_widget.h" +#include "info/profile/info_profile_actions.h" #include "info/profile/info_profile_icon.h" +#include "info/profile/info_profile_widget.h" #include "info/stories/info_stories_widget.h" #include "info/info_controller.h" #include "info/info_memento.h" @@ -25,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" +#include "ui/vertical_list.h" #include "styles/style_dialogs.h" #include "styles/style_info.h" #include "styles/style_settings.h" @@ -102,11 +106,15 @@ InnerWidget::InnerWidget( void InnerWidget::setupTop() { const auto key = _controller->key(); const auto peer = key.storiesPeer(); - if (peer - && key.storiesTab() == Stories::Tab::Saved - && peer->owner().stories().hasArchive(peer) - && _isStackBottom) { - createButtons(); + if (peer && key.storiesTab() == Stories::Tab::Saved && _isStackBottom) { + if (peer->isSelf()) { + createProfileTop(); + } else if (peer->owner().stories().hasArchive(peer)) { + createButtons(); + } else { + _top.destroy(); + refreshHeight(); + } } else if (peer && key.storiesTab() == Stories::Tab::Archive) { createAboutArchive(); } else { @@ -115,23 +123,57 @@ void InnerWidget::setupTop() { } } -void InnerWidget::createButtons() { +void InnerWidget::startTop() { _top.create(this); _top->show(); _topHeight = _top->heightValue(); +} + +void InnerWidget::createProfileTop() { + const auto key = _controller->key(); + const auto peer = key.storiesPeer(); + + startTop(); + Profile::AddCover(_top, _controller, peer, nullptr); + Profile::AddDetails(_top, _controller, peer, nullptr, { v::null }); + + auto tracker = Ui::MultiSlideTracker(); + const auto dividerWrap = _top->add( + object_ptr>( + _top, + object_ptr(_top))); + const auto divider = dividerWrap->entity(); + Ui::AddDivider(divider); + Ui::AddSkip(divider); + + addGiftsButton(tracker); + addArchiveButton(tracker); + addRecentButton(tracker); + + dividerWrap->toggleOn(tracker.atLeastOneShownValue()); + + finalizeTop(); +} + +void InnerWidget::createButtons() { + startTop(); + auto tracker = Ui::MultiSlideTracker(); + addArchiveButton(tracker); + addRecentButton(tracker); + finalizeTop(); +} + +void InnerWidget::addArchiveButton(Ui::MultiSlideTracker &tracker) { + Expects(_top != nullptr); const auto key = _controller->key(); const auto peer = key.storiesPeer(); const auto stories = &peer->owner().stories(); - const auto archive = _top->add(object_ptr( - _top, - tr::lng_stories_archive_button(), - st::infoSharedMediaButton)); - archive->addClickHandler([=] { - _controller->showSection(Info::Stories::Make( - _controller->key().storiesPeer(), - Stories::Tab::Archive)); - }); + + if (!stories->archiveCountKnown(peer->id)) { + stories->archiveLoadMore(peer->id); + } + auto count = rpl::single( rpl::empty ) | rpl::then( @@ -140,19 +182,50 @@ void InnerWidget::createButtons() { rpl::mappers::_1 == peer->id ) | rpl::to_empty ) | rpl::map([=] { - const auto value = stories->archiveCount(peer->id); - return (value > 0) ? QString::number(value) : QString(); + return stories->archiveCount(peer->id); + }) | rpl::start_spawning(_top->lifetime()); + + const auto archiveWrap = _top->add( + object_ptr>( + _top, + object_ptr( + _top, + tr::lng_stories_archive_button(), + st::infoSharedMediaButton)) + )->setDuration( + st::infoSlideDuration + )->toggleOn(rpl::duplicate(count) | rpl::map(rpl::mappers::_1 > 0)); + + const auto archive = archiveWrap->entity(); + archive->addClickHandler([=] { + _controller->showSection(Info::Stories::Make( + _controller->key().storiesPeer(), + Stories::Tab::Archive)); + }); + auto label = rpl::duplicate( + count + ) | rpl::filter( + rpl::mappers::_1 > 0 + ) | rpl::map([=](int count) { + return (count > 0) ? QString::number(count) : QString(); }); ::Settings::CreateRightLabel( archive, - std::move(count), + std::move(label), st::infoSharedMediaButton, tr::lng_stories_archive_button()); object_ptr( archive, st::infoIconMediaStoriesArchive, st::infoSharedMediaButtonIconPosition)->show(); + tracker.track(archiveWrap); +} +void InnerWidget::addRecentButton(Ui::MultiSlideTracker &tracker) { + Expects(_top != nullptr); + + const auto key = _controller->key(); + const auto peer = key.storiesPeer(); const auto recentWrap = _top->add( object_ptr>( _top, @@ -207,13 +280,64 @@ void InnerWidget::createButtons() { ) | rpl::map([](const Content &content) { return !content.elements.empty(); })); + tracker.track(recentWrap); +} - _top->add(object_ptr( - _top, - st::infoProfileSkip)); - _top->add(object_ptr(_top)); +void InnerWidget::addGiftsButton(Ui::MultiSlideTracker &tracker) { + Expects(_top != nullptr); + + const auto key = _controller->key(); + const auto peer = key.storiesPeer(); + const auto user = peer->asUser(); + Assert(user != nullptr); + + auto count = Profile::PeerGiftsCountValue( + user + ) | rpl::start_spawning(_top->lifetime()); + + const auto giftsWrap = _top->add( + object_ptr>( + _top, + object_ptr( + _top, + tr::lng_peer_gifts_title(), + st::infoSharedMediaButton)) + )->setDuration( + st::infoSlideDuration + )->toggleOn(rpl::duplicate(count) | rpl::map(rpl::mappers::_1 > 0)); + + const auto gifts = giftsWrap->entity(); + gifts->addClickHandler([=] { + _controller->showSection( + std::make_shared( + user, + Section::Type::PeerGifts)); + }); + auto label = rpl::duplicate( + count + ) | rpl::filter( + rpl::mappers::_1 > 0 + ) | rpl::map([=](int count) { + return (count > 0) ? QString::number(count) : QString(); + }); + ::Settings::CreateRightLabel( + gifts, + std::move(label), + st::infoSharedMediaButton, + tr::lng_stories_archive_button()); + object_ptr( + gifts, + st::infoIconMediaGifts, + st::infoSharedMediaButtonIconPosition)->show(); + tracker.track(giftsWrap); +} + +void InnerWidget::finalizeTop() { + Ui::AddSkip(_top, st::infoProfileSkip); + Ui::AddDivider(_top); _top->resizeToWidth(width()); + _top->heightValue( ) | rpl::start_with_next([=] { refreshHeight(); @@ -221,9 +345,7 @@ void InnerWidget::createButtons() { } void InnerWidget::createAboutArchive() { - _top.create(this); - _top->show(); - _topHeight = _top->heightValue(); + startTop(); const auto peer = _controller->key().storiesPeer(); _top->add(object_ptr( @@ -236,11 +358,7 @@ void InnerWidget::createAboutArchive() { st::infoStoriesAboutArchive), st::infoStoriesAboutArchivePadding)); - _top->resizeToWidth(width()); - _top->heightValue( - ) | rpl::start_with_next([=] { - refreshHeight(); - }, _top->lifetime()); + finalizeTop(); } void InnerWidget::visibleTopBottomUpdated( diff --git a/Telegram/SourceFiles/info/stories/info_stories_inner_widget.h b/Telegram/SourceFiles/info/stories/info_stories_inner_widget.h index 0aaeed54d..75d365427 100644 --- a/Telegram/SourceFiles/info/stories/info_stories_inner_widget.h +++ b/Telegram/SourceFiles/info/stories/info_stories_inner_widget.h @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui { class VerticalLayout; +class MultiSlideTracker; } // namespace Ui namespace Info { @@ -65,8 +66,15 @@ private: void setupTop(); void createButtons(); + void createProfileTop(); void createAboutArchive(); + void startTop(); + void addArchiveButton(Ui::MultiSlideTracker &tracker); + void addRecentButton(Ui::MultiSlideTracker &tracker); + void addGiftsButton(Ui::MultiSlideTracker &tracker); + void finalizeTop(); + object_ptr setupList(); const not_null _controller; diff --git a/Telegram/SourceFiles/info/stories/info_stories_widget.cpp b/Telegram/SourceFiles/info/stories/info_stories_widget.cpp index 2abf102d5..30052bc92 100644 --- a/Telegram/SourceFiles/info/stories/info_stories_widget.cpp +++ b/Telegram/SourceFiles/info/stories/info_stories_widget.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/stories/info_stories_widget.h" +#include "data/data_peer.h" #include "info/stories/info_stories_inner_widget.h" #include "info/info_controller.h" #include "info/info_memento.h" @@ -107,8 +108,11 @@ void Widget::selectionAction(SelectionAction action) { } rpl::producer Widget::title() { + const auto peer = controller()->key().storiesPeer(); return (controller()->key().storiesTab() == Tab::Archive) ? tr::lng_stories_archive_title() + : (peer && peer->isSelf()) + ? tr::lng_menu_my_profile() : tr::lng_stories_my_title(); } diff --git a/Telegram/SourceFiles/settings/settings_main.cpp b/Telegram/SourceFiles/settings/settings_main.cpp index f1512531c..e0b68cc32 100644 --- a/Telegram/SourceFiles/settings/settings_main.cpp +++ b/Telegram/SourceFiles/settings/settings_main.cpp @@ -800,7 +800,7 @@ void Main::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) { addAction( tr::lng_settings_information(tr::now), [=] { showOther(Information::Id()); }, - &st::menuIconInfo); + &st::menuIconEdit); } const auto window = &_controller->window(); addAction({ diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 2f97454dd..d8aed3037 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -722,6 +722,23 @@ void MainMenu::setupMenu() { std::move(descriptor)); }; if (!_controller->session().supportMode()) { + _menu->add( + CreateButtonWithIcon( + _menu, + tr::lng_menu_my_profile(), + st::mainMenuButton, + { &st::menuIconProfile }) + )->setClickedCallback([=] { + controller->showSection( + Info::Stories::Make(controller->session().user())); + }); + + SetupMenuBots(_menu, controller); + + _menu->add( + object_ptr(_menu), + { 0, st::mainMenuSkip, 0, st::mainMenuSkip }); + AddMyChannelsBox(addAction( tr::lng_create_group_title(), { &st::menuIconGroups } @@ -740,40 +757,9 @@ void MainMenu::setupMenu() { } }); - const auto wrap = _menu->add( - object_ptr>( - _menu, - CreateButtonWithIcon( - _menu, - tr::lng_menu_my_stories(), - st::mainMenuButton, - IconDescriptor{ &st::menuIconStoriesSavedSection }))); - const auto selfId = controller->session().userPeerId(); - const auto stories = &controller->session().data().stories(); - if (stories->archiveCount(selfId) > 0) { - wrap->toggle(true, anim::type::instant); - } else { - wrap->toggle(false, anim::type::instant); - if (!stories->archiveCountKnown(selfId)) { - stories->archiveLoadMore(selfId); - wrap->toggleOn(stories->archiveChanged( - ) | rpl::filter( - rpl::mappers::_1 == selfId - ) | rpl::map([=] { - return stories->archiveCount(selfId) > 0; - }) | rpl::filter(rpl::mappers::_1) | rpl::take(1)); - } - } - wrap->entity()->setClickedCallback([=] { - controller->showSection( - Info::Stories::Make(controller->session().user())); - }); - - SetupMenuBots(_menu, controller); - addAction( tr::lng_menu_contacts(), - { &st::menuIconProfile } + { &st::menuIconUserShow } )->setClickedCallback([=] { controller->show(PrepareContactsBox(controller)); });