From 70ca3d4f1ac78f25020dde44fd0425fd80575bdb Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 11 Jul 2023 19:22:18 +0400 Subject: [PATCH] Show hidden stories in archive. --- Telegram/Resources/langs/lang.strings | 8 +- .../SourceFiles/dialogs/dialogs_widget.cpp | 233 ++++++++++++------ Telegram/SourceFiles/dialogs/dialogs_widget.h | 18 +- .../dialogs/ui/dialogs_stories_content.cpp | 8 +- .../dialogs/ui/dialogs_stories_list.cpp | 113 ++++----- .../dialogs/ui/dialogs_stories_list.h | 13 +- Telegram/SourceFiles/ui/chat/more_chats_bar.h | 4 + Telegram/SourceFiles/ui/menu_icons.style | 1 - Telegram/lib_ui | 2 +- 9 files changed, 241 insertions(+), 159 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 3130497ee..d360b8957 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3823,8 +3823,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_userpic_builder_emoji_subtitle" = "Choose sticker or emoji"; "lng_stories_my_name" = "My Story"; -"lng_stories_hide_to_contacts" = "Hide"; -"lng_stories_show_in_chats" = "Show in Chats"; +"lng_stories_archive" = "Archive"; +"lng_stories_unarchive" = "Unarchive"; "lng_stories_row_count#one" = "{count} Story"; "lng_stories_row_count#other" = "{count} Stories"; "lng_stories_row_unread_and_one" = "{accumulated}, {user}"; @@ -3841,8 +3841,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_stories_archive_title" = "Stories Archive"; "lng_stories_archive_about" = "Only you can see archived stories unless you choose to save them to your profile."; "lng_stories_reply_sent" = "Message Sent"; -"lng_stories_hidden_to_contacts" = "Stories of {user} were moved to **Contacts**."; -"lng_stories_shown_in_chats" = "Stories of {user} were moved above the **Chats List**."; +"lng_stories_hidden_to_contacts" = "Stories of {user} were moved to **Archive**."; +"lng_stories_shown_in_chats" = "Stories of {user} were moved to the **Chats List**."; "lng_stories_delete_one_sure" = "Are you sure you want to delete this story?"; "lng_stories_delete_sure#one" = "Are you sure you want to delete {count} story?"; "lng_stories_delete_sure#other" = "Are you sure you want to delete {count} stories?"; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 74fbf9e6c..fb92cbf1e 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -215,12 +215,12 @@ Widget::Widget( , _lockUnlock(_searchControls, st::dialogsLock) , _scroll(this) , _scrollToTop(_scroll, st::dialogsToUp) -, _stories(std::make_unique( - this, - st::dialogsStoriesList, - Stories::ContentForSession( - &controller->session(), - Data::StorySourcesList::NotHidden))) +, _stories((_layout != Layout::Child) + ? std::make_unique( + this, + st::dialogsStoriesList, + _storiesContents.events() | rpl::flatten_latest()) + : nullptr) , _searchTimer([=] { searchMessages(); }) , _singleMessageSearch(&controller->session()) { const auto makeChildListShown = [](PeerId peerId, float64 shown) { @@ -237,46 +237,6 @@ Widget::Widget( _childListShown.value(), makeChildListShown))); _scrollToTop->raise(); - rpl::combine( - _scroll->positionValue(), - _scroll->movementValue(), - _storiesExplicitExpandValue.value() - ) | rpl::start_with_next([=]( - Ui::ElasticScrollPosition position, - Ui::ElasticScrollMovement movement, - int explicitlyExpanded) { - const auto overscrollTop = std::max(-position.overscroll, 0); - if (overscrollTop > 0 && _storiesExplicitExpand) { - _scroll->setOverscrollDefaults( - -st::dialogsStoriesFull.height, - 0, - true); - } - if (explicitlyExpanded > 0 && explicitlyExpanded < overscrollTop) { - _storiesExplicitExpandAnimation.stop(); - _storiesExplicitExpand = false; - _storiesExplicitExpandValue = 0; - return; - } - const auto above = std::max(explicitlyExpanded, overscrollTop); - if (_aboveScrollAdded != above) { - _aboveScrollAdded = above; - if (_updateScrollGeometryCached) { - _updateScrollGeometryCached(); - } - } - using Phase = Ui::ElasticScrollMovement; - _stories->setExpandedHeight( - _aboveScrollAdded, - (movement == Phase::Momentum || movement == Phase::Returning) - && (explicitlyExpanded < above)); - if (position.overscroll > 0 - || (position.value - > (_storiesExplicitExpandScrollTop - + st::dialogsRowHeight))) { - storiesToggleExplicitExpand(false); - } - }, lifetime()); _inner->updated( ) | rpl::start_with_next([=] { @@ -417,7 +377,9 @@ Widget::Widget( setupMainMenuToggle(); setupShortcuts(); - setupStories(); + if (_stories) { + setupStories(); + } _searchForNarrowFilters->setClickedCallback([=] { _filter->setFocusFast(); @@ -609,14 +571,8 @@ void Widget::scrollToDefaultChecked(bool verytop) { void Widget::setupScrollUpButton() { _scrollToTop->setClickedCallback([=] { scrollToDefaultChecked(); }); - base::install_event_filter(_scrollToTop, [=](not_null event) { - if (event->type() != QEvent::Wheel) { - return base::EventFilterResult::Continue; - } - return _scroll->viewportEvent(event) - ? base::EventFilterResult::Cancel - : base::EventFilterResult::Continue; - }); + trackScroll(_scrollToTop); + trackScroll(this); updateScrollUpVisibility(); } @@ -628,7 +584,7 @@ void Widget::setupMoreChatsBar() { ) | rpl::start_with_next([=](FilterId id) { storiesToggleExplicitExpand(false); - if (!id && false) { // #TODO stories testing + if (!id) { _moreChatsBar = nullptr; updateControlsGeometry(); return; @@ -638,6 +594,8 @@ void Widget::setupMoreChatsBar() { this, filters->moreChatsContent(id)); + trackScroll(_moreChatsBar->wrap()); + _moreChatsBar->barClicks( ) | rpl::start_with_next([=] { if (const auto missing = filters->moreChats(id) @@ -810,11 +768,64 @@ void Widget::setupMainMenuToggle() { } void Widget::setupStories() { + trackScroll(_stories.get()); + + _storiesContents.fire(Stories::ContentForSession( + &controller()->session(), + Data::StorySourcesList::NotHidden)); + + const auto currentSource = [=] { + using List = Data::StorySourcesList; + return _openedFolder ? List::Hidden : List::NotHidden; + }; + + rpl::combine( + _scroll->positionValue(), + _scroll->movementValue(), + _storiesExplicitExpandValue.value() + ) | rpl::start_with_next([=]( + Ui::ElasticScrollPosition position, + Ui::ElasticScrollMovement movement, + int explicitlyExpanded) { + if (_stories->isHidden()) { + return; + } + const auto overscrollTop = std::max(-position.overscroll, 0); + if (overscrollTop > 0 && _storiesExplicitExpand) { + _scroll->setOverscrollDefaults( + -st::dialogsStoriesFull.height, + 0, + true); + } + if (explicitlyExpanded > 0 && explicitlyExpanded < overscrollTop) { + _storiesExplicitExpandAnimation.stop(); + _storiesExplicitExpand = false; + _storiesExplicitExpandValue = 0; + return; + } + const auto above = std::max(explicitlyExpanded, overscrollTop); + if (_aboveScrollAdded != above) { + _aboveScrollAdded = above; + if (_updateScrollGeometryCached) { + _updateScrollGeometryCached(); + } + } + using Phase = Ui::ElasticScrollMovement; + _stories->setExpandedHeight( + _aboveScrollAdded, + (movement == Phase::Momentum || movement == Phase::Returning) + && (explicitlyExpanded < above)); + if (position.overscroll > 0 + || (position.value + > (_storiesExplicitExpandScrollTop + + st::dialogsRowHeight))) { + storiesToggleExplicitExpand(false); + } + }, lifetime()); + _stories->clicks( ) | rpl::start_with_next([=](uint64 id) { - controller()->openPeerStories( - PeerId(int64(id)), - Data::StorySourcesList::NotHidden); + controller()->openPeerStories(PeerId(int64(id)), currentSource()); }, lifetime()); _stories->showMenuRequests( @@ -824,8 +835,7 @@ void Widget::setupStories() { _stories->loadMoreRequests( ) | rpl::start_with_next([=] { - session().data().stories().loadMore( - Data::StorySourcesList::NotHidden); + session().data().stories().loadMore(currentSource()); }, lifetime()); _stories->toggleExpandedRequests( @@ -860,6 +870,20 @@ void Widget::storiesToggleExplicitExpand(bool expand) { }, expand ? 0 : height, expand ? height : 0, duration, anim::sineInOut); } +void Widget::trackScroll(not_null widget) { + widget->events( + ) | rpl::start_with_next([=](not_null e) { + const auto type = e->type(); + if (type == QEvent::TouchBegin + || type == QEvent::TouchUpdate + || type == QEvent::TouchEnd + || type == QEvent::TouchCancel + || type == QEvent::Wheel) { + _scroll->viewportEvent(e); + } + }, widget->lifetime()); +} + void Widget::setupShortcuts() { Shortcuts::Requests( ) | rpl::filter([=] { @@ -902,6 +926,7 @@ void Widget::fullSearchRefreshOn(rpl::producer<> events) { void Widget::updateControlsVisibility(bool fast) { updateLoadMoreChatsVisibility(); _scroll->show(); + updateStoriesVisibility(); if ((_openedFolder || _openedForum) && _filter->hasFocus()) { setInnerFocus(); } @@ -1002,9 +1027,16 @@ void Widget::changeOpenedFolder(Data::Folder *folder, anim::type animated) { cancelSearch(); closeChildList(anim::type::instant); controller()->closeForum(); + const auto was = (_openedFolder != nullptr); _openedFolder = folder; _inner->changeOpenedFolder(folder); storiesToggleExplicitExpand(false); + if (was != (_openedFolder != nullptr)) { + using List = Data::StorySourcesList; + _storiesContents.fire(Stories::ContentForSession( + &controller()->session(), + folder ? List::Hidden : List::NotHidden)); + } }, (folder != nullptr), animated); } @@ -1019,6 +1051,7 @@ void Widget::changeOpenedForum(Data::Forum *forum, anim::type animated) { _api.request(base::take(_topicSearchRequest)).cancel(); _inner->changeOpenedForum(forum); storiesToggleExplicitExpand(false); + updateStoriesVisibility(); }, (forum != nullptr), animated); } @@ -1032,6 +1065,9 @@ void Widget::refreshTopBars() { if (_openedFolder || _openedForum) { if (!_subsectionTopBar) { _subsectionTopBar.create(this, controller()); + if (_stories) { + _stories->raise(); + } _subsectionTopBar->searchCancelled( ) | rpl::start_with_next([=] { escape(); @@ -1306,6 +1342,7 @@ void Widget::startWidthAnimation() { _widthAnimationCache = Ui::PixmapFromImage(std::move(image)); _scroll->setGeometry(scrollGeometry); _scroll->hide(); + updateStoriesVisibility(); } void Widget::stopWidthAnimation() { @@ -1313,9 +1350,41 @@ void Widget::stopWidthAnimation() { if (!_showAnimation) { _scroll->show(); } + updateStoriesVisibility(); update(); } +void Widget::updateStoriesVisibility() { + if (!_stories) { + return; + } + const auto hidden = (_showAnimation != nullptr) + || _openedForum + || !_widthAnimationCache.isNull() + || _childList + || !_filter->getLastText().isEmpty() + || _searchInChat; + if (_stories->isHidden() != hidden) { + _stories->setVisible(!hidden); + using Type = Ui::ElasticScroll::OverscrollType; + if (hidden) { + _scroll->setOverscrollDefaults(0, 0); + _scroll->setOverscrollTypes(Type::Real, Type::Real); + if (_scroll->position().overscroll < 0) { + _scroll->scrollToY(0); + } + } else { + _scroll->setOverscrollDefaults(0, 0); + _scroll->setOverscrollTypes(Type::Virtual, Type::Real); + _storiesExplicitExpandValue.force_assign( + _storiesExplicitExpandValue.current()); + } + if (_aboveScrollAdded > 0 && _updateScrollGeometryCached) { + _updateScrollGeometryCached(); + } + } +} + void Widget::showFast() { if (isHidden()) { _inner->clearSelection(); @@ -1358,6 +1427,9 @@ void Widget::startSlideAnimation( QPixmap newContentCache, Window::SlideDirection direction) { _scroll->hide(); + if (_stories) { + _stories->hide(); + } _searchControls->hide(); if (_subsectionTopBar) { _subsectionTopBar->hide(); @@ -2166,6 +2238,7 @@ void Widget::applyFilterUpdate(bool force) { return; } + updateStoriesVisibility(); const auto filterText = currentSearchQuery(); _inner->applyFilterUpdate(filterText, force); if (filterText.isEmpty() && !_searchFromAuthor) { @@ -2319,6 +2392,7 @@ void Widget::closeChildList(anim::type animated) { } else { _childListShadow = nullptr; } + updateStoriesVisibility(); } void Widget::searchInChat(Key chat) { @@ -2372,6 +2446,7 @@ bool Widget::setSearchInChat(Key chat, PeerData *from) { _searchInChat = chat; controller()->searchInChat = _searchInChat; updateJumpToDateVisibility(); + updateStoriesVisibility(); } if (searchFromUpdated) { updateSearchFromVisibility(); @@ -2614,9 +2689,11 @@ void Widget::updateControlsGeometry() { const auto storiesHeight = 2 * st::dialogsStories.photoTop + st::dialogsStories.photo; const auto added = (st::dialogsFilter.heightMin - storiesHeight) / 2; - _stories->setLayoutConstraints( - { filterLeft + filterWidth, filterTop + added }, - { 0, expandedStoriesTop, barw, st::dialogsStoriesFull.height }); + if (_stories) { + _stories->setLayoutConstraints( + { filterLeft + filterWidth, filterTop + added }, + { 0, expandedStoriesTop, barw, st::dialogsStoriesFull.height }); + } if (_forumTopShadow) { _forumTopShadow->setGeometry( 0, @@ -2650,43 +2727,49 @@ void Widget::updateControlsGeometry() { ? wasScrollTop : (wasScrollTop + _topDelta); - const auto scrollw = _childList ? _narrowWidth : barw; + const auto scrollWidth = _childList ? _narrowWidth : barw; + if (_moreChatsBar) { + _moreChatsBar->resizeToWidth(barw); + } + if (_forumGroupCallBar) { + _forumGroupCallBar->resizeToWidth(barw); + } + if (_forumRequestsBar) { + _forumRequestsBar->resizeToWidth(barw); + } _updateScrollGeometryCached = [=] { - const auto moreChatsBarTop = expandedStoriesTop + _aboveScrollAdded; + const auto moreChatsBarTop = expandedStoriesTop + + ((!_stories || _stories->isHidden()) ? 0 : _aboveScrollAdded); if (_moreChatsBar) { _moreChatsBar->move(0, moreChatsBarTop); - _moreChatsBar->resizeToWidth(barw); } const auto forumGroupCallTop = moreChatsBarTop + (_moreChatsBar ? _moreChatsBar->height() : 0); if (_forumGroupCallBar) { _forumGroupCallBar->move(0, forumGroupCallTop); - _forumGroupCallBar->resizeToWidth(barw); } const auto forumRequestsTop = forumGroupCallTop + (_forumGroupCallBar ? _forumGroupCallBar->height() : 0); if (_forumRequestsBar) { _forumRequestsBar->move(0, forumRequestsTop); - _forumRequestsBar->resizeToWidth(barw); } const auto forumReportTop = forumRequestsTop + (_forumRequestsBar ? _forumRequestsBar->height() : 0); if (_forumReportBar) { _forumReportBar->bar().move(0, forumReportTop); } - auto scrollTop = forumReportTop + const auto scrollTop = forumReportTop + (_forumReportBar ? _forumReportBar->bar().height() : 0); - auto scrollHeight = height() - scrollTop; - + const auto scrollHeight = height() - scrollTop; const auto wasScrollHeight = _scroll->height(); - _scroll->setGeometry(0, scrollTop, scrollw, scrollHeight); + _scroll->setGeometry(0, scrollTop, scrollWidth, scrollHeight); if (scrollHeight != wasScrollHeight) { controller()->floatPlayerAreaUpdated(); } }; _updateScrollGeometryCached(); - _inner->resize(scrollw, _inner->height()); + _inner->resize(scrollWidth, _inner->height()); _inner->setNarrowRatio(narrowRatio); if (newScrollTop != wasScrollTop) { _scroll->scrollToY(newScrollTop); @@ -2698,7 +2781,7 @@ void Widget::updateControlsGeometry() { } if (_childList) { - const auto childw = std::max(_narrowWidth, width() - scrollw); + const auto childw = std::max(_narrowWidth, width() - scrollWidth); const auto childh = _scroll->y() + _scroll->height(); const auto childx = width() - childw; _childList->setGeometryWithTopMoved( diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index ca83fefa1..245998392 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -58,6 +58,7 @@ struct SectionShow; namespace Dialogs::Stories { class List; +struct Content; } // namespace Dialogs::Stories namespace Dialogs { @@ -168,6 +169,7 @@ private: void setupShortcuts(); void setupStories(); void storiesToggleExplicitExpand(bool expand); + void trackScroll(not_null widget); [[nodiscard]] bool searchForPeersRequired(const QString &query) const; [[nodiscard]] bool searchForTopicsRequired(const QString &query) const; bool setSearchInChat(Key chat, PeerData *from = nullptr); @@ -179,6 +181,7 @@ private: void updateControlsVisibility(bool fast = false); void updateLockUnlockVisibility(); void updateLoadMoreChatsVisibility(); + void updateStoriesVisibility(); void updateJumpToDateVisibility(bool fast = false); void updateSearchFromVisibility(bool fast = false); void updateControlsGeometry(); @@ -268,6 +271,14 @@ private: bool _scrollToTopIsShown = false; bool _forumSearchRequested = false; + Data::Folder *_openedFolder = nullptr; + Data::Forum *_openedForum = nullptr; + Dialogs::Key _searchInChat; + History *_searchInMigrated = nullptr; + PeerData *_searchFromAuthor = nullptr; + QString _lastFilterText; + + rpl::event_stream> _storiesContents; Fn _updateScrollGeometryCached; std::unique_ptr _stories; Ui::Animations::Simple _storiesExplicitExpandAnimation; @@ -276,13 +287,6 @@ private: int _aboveScrollAdded = 0; bool _storiesExplicitExpand = false; - Data::Folder *_openedFolder = nullptr; - Data::Forum *_openedForum = nullptr; - Dialogs::Key _searchInChat; - History *_searchInMigrated = nullptr; - PeerData *_searchFromAuthor = nullptr; - QString _lastFilterText; - base::Timer _searchTimer; QString _peerSearchQuery; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_content.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_content.cpp index b882842ca..2f6c55dd1 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_content.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_content.cpp @@ -503,14 +503,14 @@ void FillSourceMenu( controller->uiShow()); }; if (in(Data::StorySourcesList::NotHidden)) { - add(tr::lng_stories_hide_to_contacts(tr::now), [=] { + add(tr::lng_stories_archive(tr::now), [=] { toggle(false); - }, &st::menuIconCancel); + }, &st::menuIconArchive); } if (in(Data::StorySourcesList::Hidden)) { - add(tr::lng_stories_show_in_chats(tr::now), [=] { + add(tr::lng_stories_unarchive(tr::now), [=] { toggle(true); - }, &st::menuIconStoriesToChats); + }, &st::menuIconUnarchive); } } } diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.cpp index 2d3ca0d76..dc6384a8d 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.cpp @@ -21,8 +21,8 @@ namespace { constexpr auto kSmallThumbsShown = 3; constexpr auto kSummaryExpandLeft = 1; constexpr auto kPreloadPages = 2; -constexpr auto kExpandAfterRatio = 0.85; -constexpr auto kCollapseAfterRatio = 0.72; +constexpr auto kExpandAfterRatio = 0.72; +constexpr auto kCollapseAfterRatio = 0.68; constexpr auto kFrictionRatio = 0.15; constexpr auto kExpandCatchUpDuration = crl::time(200); @@ -66,7 +66,6 @@ List::List( showContent(std::move(content)); }, lifetime()); - _shownAnimation.stop(); setMouseTracking(true); resize(0, _data.empty() ? 0 : st.full.height); } @@ -76,18 +75,13 @@ void List::showContent(Content &&content) { return; } if (content.elements.empty()) { - _hidingData = base::take(_data); - if (!_hidingData.empty()) { - toggleAnimated(false); - } + _data = {}; + _empty = true; return; } - const auto hidden = _content.elements.empty(); - const auto wasCount = int((hidden ? _hidingData : _data).items.size()); + const auto wasCount = int(_data.items.size()); _content = std::move(content); - auto items = base::take( - _data.items.empty() ? _hidingData.items : _data.items); - _hidingData = {}; + auto items = base::take(_data.items); _data.items.reserve(_content.elements.size()); for (const auto &element : _content.elements) { const auto id = element.id; @@ -117,8 +111,8 @@ void List::showContent(Content &&content) { updateScrollMax(); updateSummary(_data); update(); - if (hidden) { - toggleAnimated(true); + if (!wasCount) { + _empty = false; } } @@ -204,24 +198,6 @@ void List::updateSummary(Data &data) { Populate(_st.small, data.summaries); } -void List::toggleAnimated(bool shown) { - _shownAnimation.start( - [=] { updateHeight(); }, - shown ? 0. : 1., - shown ? 1. : 0., - st::slideWrapDuration); -} - -void List::updateHeight() { - const auto shown = _shownAnimation.value(_data.empty() ? 0. : 1.); - resize( - width(), - anim::interpolate(0, _st.full.height, shown)); - if (_data.empty() && shown == 0.) { - _hidingData = {}; - } -} - void List::updateScrollMax() { const auto &full = _st.full; const auto singleFull = full.photoLeft * 2 + full.photo; @@ -256,7 +232,7 @@ void List::requestExpanded(bool expanded) { if (_expanded != expanded) { _expanded = expanded; _expandedAnimation.start( - [=] { update(); }, + [=] { checkForFullState(); update(); }, _expanded ? 0. : 1., _expanded ? 1. : 0., st::slideWrapDuration, @@ -308,15 +284,14 @@ List::Layout List::computeLayout() { const auto lerp = [&](float64 a, float64 b) { return a + (b - a) * ratio; }; - auto &rendering = _data.empty() ? _hidingData : _data; const auto singleFull = full.photoLeft * 2 + full.photo; - const auto itemsCount = int(rendering.items.size()); + const auto itemsCount = int(_data.items.size()); const auto narrowWidth = st::defaultDialogRow.padding.left() + st::defaultDialogRow.photoSize + st::defaultDialogRow.padding.left(); const auto narrow = false;// (width() <= narrowWidth); const auto smallSkip = (itemsCount > 1 - && rendering.items[0].element.skipSmall) + && _data.items[0].element.skipSmall) ? 1 : 0; const auto smallCount = std::min( @@ -378,7 +353,6 @@ void List::paintEvent(QPaintEvent *e) { const auto elerp = [&](float64 a, float64 b) { return a + (b - a) * expandRatio; }; - auto &rendering = _data.empty() ? _hidingData : _data; const auto line = elerp(st.lineTwice, full.lineTwice) / 2.; const auto lineRead = elerp(st.lineReadTwice, full.lineReadTwice) / 2.; const auto photoTopSmall = st.photoTop; @@ -389,7 +363,8 @@ void List::paintEvent(QPaintEvent *e) { - (st.photoTop + (st.photo / 2.)) + (photoTop + (photo / 2.)); const auto nameScale = _lastRatio; - const auto nameTop = nameScale * full.nameTop; + const auto nameTop = full.nameTop + + (photoTop + photo - full.photoTop - full.photo); const auto nameWidth = nameScale * AvailableNameWidth(_st); const auto nameHeight = nameScale * full.nameStyle.font->height; const auto nameLeft = layout.photoLeft + (photo - nameWidth) / 2.; @@ -402,11 +377,11 @@ void List::paintEvent(QPaintEvent *e) { const auto left = anim::interpolate( _changingGeometryFrom.x(), _geometryFull.x(), - layout.expandedRatio); + layout.ratio); const auto top = anim::interpolate( _changingGeometryFrom.y(), _geometryFull.y(), - layout.expandedRatio); + layout.ratio); p.translate(QPoint(left, top) - pos()); } @@ -433,18 +408,19 @@ void List::paintEvent(QPaintEvent *e) { const auto lookup = [&](int index) { const auto indexSmall = layout.startIndexSmall + index; const auto indexFull = layout.startIndexFull + index; + const auto k = (photoTop - photoTopSmall); const auto ySmall = photoTopSmall - + ((indexSmall - layout.smallSkip + 1) - * (photoTop - photoTopSmall) / 3.); + + ((photoTop - photoTopSmall) + * (kSmallThumbsShown - indexSmall + layout.smallSkip) / 0.5); const auto y = elerp(ySmall, photoTop); const auto small = (drawSmall && indexSmall < layout.endIndexSmall && indexSmall >= layout.smallSkip) - ? &rendering.items[indexSmall] + ? &_data.items[indexSmall] : nullptr; const auto full = (drawFull && indexFull < layout.endIndexFull) - ? &rendering.items[indexFull] + ? &_data.items[indexFull] : nullptr; const auto x = layout.left + layout.single * index; return Single{ x, indexSmall, small, indexFull, full, y }; @@ -556,9 +532,16 @@ void List::paintEvent(QPaintEvent *e) { // White circle with possible read gray line. const auto hasReadLine = (itemFull && !fullUnread); + p.setOpacity((small && itemFull) + ? 1. + : small + ? (1. - expandRatio) + : expandRatio); if (hasReadLine) { auto color = st::dialogsUnreadBgMuted->c; - color.setAlphaF(color.alphaF() * expandRatio); + if (small) { + color.setAlphaF(color.alphaF() * expandRatio); + } auto pen = QPen(color); pen.setWidthF(lineRead); p.setPen(pen); @@ -601,7 +584,7 @@ void List::paintEvent(QPaintEvent *e) { p.setOpacity(1.); }); - paintSummary(p, rendering, summaryTop, ratio); + paintSummary(p, _data, summaryTop, ratio); } void List::validateThumbnail(not_null item) { @@ -729,7 +712,7 @@ void List::paintSummary( void List::wheelEvent(QWheelEvent *e) { const auto horizontal = (e->angleDelta().x() != 0); - if (!horizontal) { + if (!horizontal || _state == State::Small) { e->ignore(); return; } @@ -757,6 +740,10 @@ void List::wheelEvent(QWheelEvent *e) { void List::mousePressEvent(QMouseEvent *e) { if (e->button() != Qt::LeftButton) { return; + } else if (_state == State::Small) { + requestExpanded(true); + } else if (_state != State::Full) { + return; } _lastMousePosition = e->globalPos(); updateSelected(); @@ -834,25 +821,28 @@ void List::setExpandedHeight(int height, bool momentum) { _expandIgnored = false; _expandCatchUpAnimation.start([=] { update(); - if (!_expandCatchUpAnimation.animating() - && _lastExpandedHeight == _st.full.height) { - setState(State::Full); - } + checkForFullState(); }, 0., 1., kExpandCatchUpDuration); } else if (!height && _expandCatchUpAnimation.animating()) { _expandCatchUpAnimation.stop(); } _lastExpandedHeight = height; - setState(!height - ? State::Small - : (height < _st.full.height - || _expandCatchUpAnimation.animating() - || _expandedAnimation.animating()) - ? State::Changing - : State::Full); + if (!checkForFullState()) { + setState(!height ? State::Small : State::Changing); + } update(); } +bool List::checkForFullState() { + if (_expandCatchUpAnimation.animating() + || _expandedAnimation.animating() + || _lastExpandedHeight < _st.full.height) { + return false; + } + setState(State::Full); + return true; +} + void List::setLayoutConstraints(QPoint topRightSmall, QRect geometryFull) { _topRightSmall = topRightSmall; _geometryFull = geometryFull; @@ -875,7 +865,9 @@ void List::updateGeometry() { QRect List::countSmallGeometry() const { const auto &st = _st.small; const auto layout = const_cast(this)->computeLayout(); - const auto count = layout.endIndexSmall - layout.startIndexSmall; + const auto count = layout.endIndexSmall + - layout.startIndexSmall + - layout.smallSkip; const auto width = st.left + st.photoLeft + st.photo + (count - 1) * st.shift @@ -893,9 +885,6 @@ void List::setState(State state) { return; } _state = state; - setAttribute( - Qt::WA_TransparentForMouseEvents, - state == State::Changing); updateGeometry(); } diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.h b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.h index 0bf355bdb..7a02db40f 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.h @@ -68,6 +68,12 @@ public: void setExpandedHeight(int height, bool momentum = false); void setLayoutConstraints(QPoint topRightSmall, QRect geometryFull); + [[nodiscard]] bool empty() const { + return _empty.current(); + } + [[nodiscard]] rpl::producer emptyValue() const { + return _empty.value(); + } [[nodiscard]] rpl::producer clicks() const; [[nodiscard]] rpl::producer showMenuRequests() const; [[nodiscard]] rpl::producer toggleExpandedRequests() const; @@ -153,12 +159,11 @@ private: void checkLoadMore(); void requestExpanded(bool expanded); + bool checkForFullState(); void setState(State state); void updateGeometry(); [[nodiscard]] QRect countSmallGeometry() const; void updateExpanding(int expandingHeight, int expandedHeight); - void updateHeight(); - void toggleAnimated(bool shown); void paintSummary( QPainter &p, Data &data, @@ -170,7 +175,6 @@ private: const style::DialogsStoriesList &_st; Content _content; Data _data; - Data _hidingData; rpl::event_stream _clicks; rpl::event_stream _showMenuRequests; rpl::event_stream _toggleExpandedRequests; @@ -181,8 +185,7 @@ private: QRect _geometryFull; QRect _changingGeometryFrom; State _state = State::Small; - - Ui::Animations::Simple _shownAnimation; + rpl::variable _empty = true; QPoint _lastMousePosition; std::optional _mouseDownPosition; diff --git a/Telegram/SourceFiles/ui/chat/more_chats_bar.h b/Telegram/SourceFiles/ui/chat/more_chats_bar.h index 5536349c8..f920e4832 100644 --- a/Telegram/SourceFiles/ui/chat/more_chats_bar.h +++ b/Telegram/SourceFiles/ui/chat/more_chats_bar.h @@ -31,6 +31,10 @@ public: rpl::producer content); ~MoreChatsBar(); + [[nodiscard]] not_null wrap() { + return &_wrap; + } + void show(); void hide(); void raise(); diff --git a/Telegram/SourceFiles/ui/menu_icons.style b/Telegram/SourceFiles/ui/menu_icons.style index 183026881..f1b1a2029 100644 --- a/Telegram/SourceFiles/ui/menu_icons.style +++ b/Telegram/SourceFiles/ui/menu_icons.style @@ -112,7 +112,6 @@ menuIconArchiveOpen: icon {{ "menu/archive_open", menuIconColor }}; menuIconGroups: icon {{ "menu/groups", menuIconColor }}; menuIconSavedMessages: icon {{ "menu/saved_messages", menuIconColor }}; menuIconNightMode: icon {{ "menu/night_mode", menuIconColor }}; -menuIconStoriesToChats: icon {{ "menu/stories_to_chats", menuIconColor }}; menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }}; menuIconTTLAnyTextPosition: point(11px, 22px); diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 763b3a37c..427fc4c8f 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 763b3a37c34fd7819f9d553b94387c4fe16554ff +Subproject commit 427fc4c8f7c8b92cca900e0270718f83fcb16e35