Working stories in overscroll.

This commit is contained in:
John Preston 2023-07-11 11:15:32 +04:00
parent e0c10e7cc2
commit 85795aa376
10 changed files with 232 additions and 264 deletions

View File

@ -246,7 +246,7 @@ dialogsSearchForNarrowFilters: IconButton(dialogsMenuToggle) {
dialogsFilter: InputField(defaultInputField) { dialogsFilter: InputField(defaultInputField) {
textBg: filterInputInactiveBg; textBg: filterInputInactiveBg;
textBgActive: filterInputActiveBg; textBgActive: filterInputActiveBg;
textMargins: margins(12px, 7px, 30px, 3px); textMargins: margins(12px, 8px, 30px, 5px);
placeholderFg: placeholderFg; placeholderFg: placeholderFg;
placeholderFgActive: placeholderFgActive; placeholderFgActive: placeholderFgActive;
@ -257,16 +257,16 @@ dialogsFilter: InputField(defaultInputField) {
placeholderFont: normalFont; placeholderFont: normalFont;
borderFg: filterInputInactiveBg; borderFg: filterInputInactiveBg;
borderFgActive: filterInputBorderFg; borderFgActive: windowBgRipple;
borderFgError: activeLineFgError; borderFgError: activeLineFgError;
border: 2px; border: 2px;
borderActive: 2px; borderActive: 2px;
borderRadius: roundRadiusSmall; borderRadius: 18px;
font: normalFont; font: normalFont;
heightMin: 32px; heightMin: 35px;
} }
dialogsCancelSearchInPeer: IconButton(dialogsMenuToggle) { dialogsCancelSearchInPeer: IconButton(dialogsMenuToggle) {
icon: icon {{ "dialogs/dialogs_cancel_search", dialogsMenuIconFg }}; icon: icon {{ "dialogs/dialogs_cancel_search", dialogsMenuIconFg }};
@ -511,8 +511,9 @@ DialogsStoriesList {
dialogsStories: DialogsStories { dialogsStories: DialogsStories {
left: 4px; left: 4px;
height: 35px; height: 35px;
photo: 24px; photo: 21px;
photoLeft: 10px; photoTop: 4px;
photoLeft: 4px;
shift: 16px; shift: 16px;
lineTwice: 3px; lineTwice: 3px;
lineReadTwice: 0px; lineReadTwice: 0px;

View File

@ -141,13 +141,6 @@ InnerWidget::InnerWidget(
rpl::producer<ChildListShown> childListShown) rpl::producer<ChildListShown> childListShown)
: RpWidget(parent) : RpWidget(parent)
, _controller(controller) , _controller(controller)
, _stories(std::make_unique<Stories::List>(
this,
st::dialogsStoriesList,
Stories::ContentForSession(
&controller->session(),
Data::StorySourcesList::NotHidden),
[=] { return _stories->height() - _visibleTop; }))
, _shownList(controller->session().data().chatsList()->indexed()) , _shownList(controller->session().data().chatsList()->indexed())
, _st(&st::defaultDialogRow) , _st(&st::defaultDialogRow)
, _pinnedShiftAnimation([=](crl::time now) { , _pinnedShiftAnimation([=](crl::time now) {
@ -328,37 +321,6 @@ InnerWidget::InnerWidget(
switchToFilter(filterId); switchToFilter(filterId);
}, lifetime()); }, lifetime());
_stories->heightValue(
) | rpl::filter([=] {
return (_viewportHeight > 0) && (defaultScrollTop() > _visibleTop);
}) | rpl::start_with_next([=] {
refreshForDefaultScroll();
jumpToTop();
}, lifetime());
_stories->entered(
) | rpl::start_with_next([=] {
clearSelection();
}, lifetime());
_stories->clicks(
) | rpl::start_with_next([=](uint64 id) {
_controller->openPeerStories(
PeerId(int64(id)),
Data::StorySourcesList::NotHidden);
}, lifetime());
_stories->showMenuRequests(
) | rpl::start_with_next([=](const Stories::ShowMenuRequest &request) {
FillSourceMenu(_controller, request);
}, lifetime());
_stories->loadMoreRequests(
) | rpl::start_with_next([=] {
session().data().stories().loadMore(
Data::StorySourcesList::NotHidden);
}, lifetime());
session().data().stories().incrementPreloadingMainSources(); session().data().stories().incrementPreloadingMainSources();
handleChatListEntryRefreshes(); handleChatListEntryRefreshes();
@ -450,14 +412,8 @@ int InnerWidget::skipTopHeight() const {
: 0; : 0;
} }
bool InnerWidget::storiesShown() const {
return (_state == WidgetState::Default)
&& !_openedFolder
&& !_openedForum;
}
int InnerWidget::collapsedRowsOffset() const { int InnerWidget::collapsedRowsOffset() const {
return storiesShown() ? _stories->height() : 0; return 0;
} }
int InnerWidget::dialogsOffset() const { int InnerWidget::dialogsOffset() const {
@ -466,22 +422,6 @@ int InnerWidget::dialogsOffset() const {
- skipTopHeight(); - skipTopHeight();
} }
rpl::producer<bool> InnerWidget::storiesExpandedRequests() const {
return rpl::merge(
_stories->toggleExpandedRequests(),
_storiesExpandedRequests.events());
}
void InnerWidget::setTouchScrollActive(bool active) {
_stories->setTouchScrollActive(active);
}
int InnerWidget::defaultScrollTop() const {
return storiesShown()
? std::max(_stories->height() - st::dialogsStories.height, 0)
: 0;
}
int InnerWidget::fixedOnTopCount() const { int InnerWidget::fixedOnTopCount() const {
auto result = 0; auto result = 0;
for (const auto &row : *_shownList) { for (const auto &row : *_shownList) {
@ -564,7 +504,6 @@ void InnerWidget::changeOpenedFolder(Data::Folder *folder) {
stopReorderPinned(); stopReorderPinned();
clearSelection(); clearSelection();
_openedFolder = folder; _openedFolder = folder;
_stories->setVisible(storiesShown());
refreshShownList(); refreshShownList();
refreshWithCollapsedRows(true); refreshWithCollapsedRows(true);
if (_loadMoreCallback) { if (_loadMoreCallback) {
@ -591,7 +530,6 @@ void InnerWidget::changeOpenedForum(Data::Forum *forum) {
} }
_openedForum = forum; _openedForum = forum;
_st = forum ? &st::forumTopicRow : &st::defaultDialogRow; _st = forum ? &st::forumTopicRow : &st::defaultDialogRow;
_stories->setVisible(storiesShown());
refreshShownList(); refreshShownList();
_openedForumLifetime.destroy(); _openedForumLifetime.destroy();
@ -642,7 +580,6 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
.paused = videoPaused, .paused = videoPaused,
.narrow = (fullWidth < st::columnMinimalWidthLeft / 2), .narrow = (fullWidth < st::columnMinimalWidthLeft / 2),
}; };
_stories->setBgOverride(context.currentBg);
const auto fillGuard = gsl::finally([&] { const auto fillGuard = gsl::finally([&] {
// We translate painter down, but it'll be cropped below rect. // We translate painter down, but it'll be cropped below rect.
p.fillRect(rect(), context.currentBg); p.fillRect(rect(), context.currentBg);
@ -1759,13 +1696,6 @@ void InnerWidget::mousePressReleased(
} }
} }
void InnerWidget::setViewportHeight(int viewportHeight) {
if (_viewportHeight != viewportHeight) {
_viewportHeight = viewportHeight;
refreshForDefaultScroll();
}
}
void InnerWidget::setCollapsedPressed(int pressed) { void InnerWidget::setCollapsedPressed(int pressed) {
if (_collapsedPressed != pressed) { if (_collapsedPressed != pressed) {
if (_collapsedPressed >= 0) { if (_collapsedPressed >= 0) {
@ -1836,7 +1766,6 @@ void InnerWidget::setSearchedPressed(int pressed) {
} }
void InnerWidget::resizeEvent(QResizeEvent *e) { void InnerWidget::resizeEvent(QResizeEvent *e) {
_stories->resizeToWidth(width());
resizeEmptyLabel(); resizeEmptyLabel();
moveCancelSearchButtons(); moveCancelSearchButtons();
} }
@ -2597,7 +2526,6 @@ void InnerWidget::visibleTopBottomUpdated(
int visibleBottom) { int visibleBottom) {
_visibleTop = visibleTop; _visibleTop = visibleTop;
_visibleBottom = visibleBottom; _visibleBottom = visibleBottom;
_stories->update();
preloadRowsData(); preloadRowsData();
const auto loadTill = _visibleTop const auto loadTill = _visibleTop
+ PreloadHeightsCount * (_visibleBottom - _visibleTop); + PreloadHeightsCount * (_visibleBottom - _visibleTop);
@ -2793,12 +2721,6 @@ void InnerWidget::editOpenedFilter() {
} }
} }
void InnerWidget::refreshForDefaultScroll() {
if (height() < defaultScrollTop() + _viewportHeight) {
refresh();
}
}
void InnerWidget::refresh(bool toTop) { void InnerWidget::refresh(bool toTop) {
if (!_geometryInited) { if (!_geometryInited) {
return; return;
@ -2820,9 +2742,6 @@ void InnerWidget::refresh(bool toTop) {
h = searchedOffset() + (_searchResults.size() * _st->height); h = searchedOffset() + (_searchResults.size() * _st->height);
} }
} }
if (const auto storiesSkip = defaultScrollTop()) {
accumulate_max(h, storiesSkip + _viewportHeight);
}
resize(width(), h); resize(width(), h);
if (toTop) { if (toTop) {
stopReorderPinned(); stopReorderPinned();
@ -3033,10 +2952,7 @@ void InnerWidget::clearFilter() {
} }
void InnerWidget::setState(WidgetState state) { void InnerWidget::setState(WidgetState state) {
if (_state != state) { _state = state;
_state = state;
_stories->setVisible(storiesShown());
}
} }
void InnerWidget::selectSkip(int32 direction) { void InnerWidget::selectSkip(int32 direction) {
@ -3331,8 +3247,7 @@ void InnerWidget::switchToFilter(FilterId filterId) {
} }
void InnerWidget::jumpToTop() { void InnerWidget::jumpToTop() {
const auto to = defaultScrollTop(); _mustScrollTo.fire({ 0, -1 });
_mustScrollTo.fire({ to, -1 });
} }
void InnerWidget::saveChatsFilterScrollState(FilterId filterId) { void InnerWidget::saveChatsFilterScrollState(FilterId filterId) {
@ -3342,8 +3257,7 @@ void InnerWidget::saveChatsFilterScrollState(FilterId filterId) {
void InnerWidget::restoreChatsFilterScrollState(FilterId filterId) { void InnerWidget::restoreChatsFilterScrollState(FilterId filterId) {
const auto it = _chatsFilterScrollStates.find(filterId); const auto it = _chatsFilterScrollStates.find(filterId);
if (it != end(_chatsFilterScrollStates)) { if (it != end(_chatsFilterScrollStates)) {
const auto top = std::max(it->second, defaultScrollTop()); _mustScrollTo.fire({ std::max(it->second, 0), -1 });
_mustScrollTo.fire({ top, -1 });
} }
} }
@ -3412,7 +3326,6 @@ ChosenRow InnerWidget::computeChosenRow() const {
bool InnerWidget::chooseRow( bool InnerWidget::chooseRow(
Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers modifiers,
MsgId pressedTopicRootId) { MsgId pressedTopicRootId) {
_storiesExpandedRequests.fire(false);
if (chooseCollapsedRow()) { if (chooseCollapsedRow()) {
return true; return true;
} else if (chooseHashtag()) { } else if (chooseHashtag()) {

View File

@ -52,10 +52,6 @@ struct PaintContext;
struct TopicJumpCache; struct TopicJumpCache;
} // namespace Dialogs::Ui } // namespace Dialogs::Ui
namespace Dialogs::Stories {
class List;
} // namespace Dialogs::Stories
namespace Dialogs { namespace Dialogs {
class Row; class Row;
@ -105,11 +101,6 @@ public:
const QVector<MTPPeer> &my, const QVector<MTPPeer> &my,
const QVector<MTPPeer> &result); const QVector<MTPPeer> &result);
void setTouchScrollActive(bool active);
[[nodiscard]] rpl::producer<bool> storiesExpandedRequests() const;
[[nodiscard]] int defaultScrollTop() const;
void setViewportHeight(int viewportHeight);
[[nodiscard]] FilterId filterId() const; [[nodiscard]] FilterId filterId() const;
void clearSelection(); void clearSelection();
@ -124,7 +115,6 @@ public:
void clearFilter(); void clearFilter();
void refresh(bool toTop = false); void refresh(bool toTop = false);
void refreshForDefaultScroll();
void refreshEmptyLabel(); void refreshEmptyLabel();
void resizeEmptyLabel(); void resizeEmptyLabel();
@ -322,7 +312,6 @@ private:
void fillArchiveSearchMenu(not_null<Ui::PopupMenu*> menu); void fillArchiveSearchMenu(not_null<Ui::PopupMenu*> menu);
void refreshShownList(); void refreshShownList();
[[nodiscard]] bool storiesShown() const;
[[nodiscard]] int skipTopHeight() const; [[nodiscard]] int skipTopHeight() const;
[[nodiscard]] int collapsedRowsOffset() const; [[nodiscard]] int collapsedRowsOffset() const;
[[nodiscard]] int dialogsOffset() const; [[nodiscard]] int dialogsOffset() const;
@ -409,10 +398,6 @@ private:
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
const std::unique_ptr<Stories::List> _stories;
rpl::event_stream<bool> _storiesExpandedRequests;
int _viewportHeight = 0;
not_null<IndexedList*> _shownList; not_null<IndexedList*> _shownList;
FilterId _filterId = 0; FilterId _filterId = 0;
bool _mouseSelection = false; bool _mouseSelection = false;

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "dialogs/dialogs_widget.h" #include "dialogs/dialogs_widget.h"
#include "dialogs/ui/dialogs_stories_content.h"
#include "dialogs/ui/dialogs_stories_list.h"
#include "dialogs/dialogs_inner_widget.h" #include "dialogs/dialogs_inner_widget.h"
#include "dialogs/dialogs_search_from_controllers.h" #include "dialogs/dialogs_search_from_controllers.h"
#include "dialogs/dialogs_key.h" #include "dialogs/dialogs_key.h"
@ -64,6 +66,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_download_manager.h" #include "data/data_download_manager.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_stories.h"
#include "info/downloads/info_downloads_widget.h" #include "info/downloads/info_downloads_widget.h"
#include "info/info_memento.h" #include "info/info_memento.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
@ -211,15 +214,21 @@ Widget::Widget(
, _cancelSearch(_searchControls, st::dialogsCancelSearch) , _cancelSearch(_searchControls, st::dialogsCancelSearch)
, _lockUnlock(_searchControls, st::dialogsLock) , _lockUnlock(_searchControls, st::dialogsLock)
, _scroll(this) , _scroll(this)
, _allowStoriesExpandTimer([=] {
//_scroll->verticalScrollBar()->setMinimum(0);
})
, _scrollToTop(_scroll, st::dialogsToUp) , _scrollToTop(_scroll, st::dialogsToUp)
, _stories(std::make_unique<Stories::List>(
this,
st::dialogsStoriesList,
Stories::ContentForSession(
&controller->session(),
Data::StorySourcesList::NotHidden)))
, _searchTimer([=] { searchMessages(); }) , _searchTimer([=] { searchMessages(); })
, _singleMessageSearch(&controller->session()) { , _singleMessageSearch(&controller->session()) {
const auto makeChildListShown = [](PeerId peerId, float64 shown) { const auto makeChildListShown = [](PeerId peerId, float64 shown) {
return InnerWidget::ChildListShown{ peerId, shown }; return InnerWidget::ChildListShown{ peerId, shown };
}; };
_scroll->setOverscrollTypes(
Ui::ElasticScroll::OverscrollType::Virtual,
Ui::ElasticScroll::OverscrollType::Real);
_inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>( _inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>(
this, this,
controller, controller,
@ -228,6 +237,22 @@ Widget::Widget(
_childListShown.value(), _childListShown.value(),
makeChildListShown))); makeChildListShown)));
_scrollToTop->raise(); _scrollToTop->raise();
rpl::combine(
_scroll->positionValue(),
_scroll->movementValue()
) | rpl::start_with_next([=](
Ui::ElasticScrollPosition position,
Ui::ElasticScrollMovement movement) {
const auto overscrollTop = std::max(-position.overscroll, 0);
if (_overscrollTop != overscrollTop) {
_overscrollTop = overscrollTop;
updateControlsGeometry();
}
using Phase = Ui::ElasticScrollMovement;
_stories->setExpandedHeight(
_overscrollTop,
(movement == Phase::Momentum || movement == Phase::Returning));
}, lifetime());
_inner->updated( _inner->updated(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
@ -268,15 +293,6 @@ Widget::Widget(
} }
}, lifetime()); }, lifetime());
_inner->storiesExpandedRequests(
) | rpl::start_with_next([=](bool expanded) {
if (expanded || _scroll->scrollTop() < _inner->defaultScrollTop()) {
if (_scroll->scrollTop() > 0) {
scrollToDefaultChecked(expanded);
}
}
}, lifetime());
_inner->mustScrollTo( _inner->mustScrollTo(
) | rpl::start_with_next([=](const Ui::ScrollToRequest &data) { ) | rpl::start_with_next([=](const Ui::ScrollToRequest &data) {
if (_scroll) { if (_scroll) {
@ -328,12 +344,6 @@ Widget::Widget(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
listScrollUpdated(); listScrollUpdated();
}, lifetime()); }, lifetime());
_scroll->setCustomWheelProcess([=](not_null<QWheelEvent*> e) {
return customWheelProcess(e);
});
_scroll->setCustomTouchProcess([=](not_null<QTouchEvent*> e) {
return customTouchProcess(e);
});
session().data().chatsListChanges( session().data().chatsListChanges(
) | rpl::filter([=](Data::Folder *folder) { ) | rpl::filter([=](Data::Folder *folder) {
@ -383,6 +393,7 @@ Widget::Widget(
setupMainMenuToggle(); setupMainMenuToggle();
setupShortcuts(); setupShortcuts();
setupStories();
_searchForNarrowFilters->setClickedCallback([=] { _searchForNarrowFilters->setClickedCallback([=] {
_filter->setFocusFast(); _filter->setFocusFast();
@ -589,7 +600,7 @@ void Widget::setupMoreChatsBar() {
} }
controller()->activeChatsFilter( controller()->activeChatsFilter(
) | rpl::start_with_next([=](FilterId id) { ) | rpl::start_with_next([=](FilterId id) {
if (!id) { if (!id && false) { // #TODO stories testing
_moreChatsBar = nullptr; _moreChatsBar = nullptr;
updateControlsGeometry(); updateControlsGeometry();
return; return;
@ -770,6 +781,38 @@ void Widget::setupMainMenuToggle() {
}, _mainMenu.toggle->lifetime()); }, _mainMenu.toggle->lifetime());
} }
void Widget::setupStories() {
_stories->clicks(
) | rpl::start_with_next([=](uint64 id) {
controller()->openPeerStories(
PeerId(int64(id)),
Data::StorySourcesList::NotHidden);
}, lifetime());
_stories->showMenuRequests(
) | rpl::start_with_next([=](const Stories::ShowMenuRequest &request) {
FillSourceMenu(controller(), request);
}, lifetime());
_stories->loadMoreRequests(
) | rpl::start_with_next([=] {
session().data().stories().loadMore(
Data::StorySourcesList::NotHidden);
}, lifetime());
_stories->toggleExpandedRequests(
) | rpl::start_with_next([=](bool expanded) {
if (expanded) {
if (!_scrollToAnimation.animating() || _scrollAnimationTo) {
scrollToDefault();
}
}
_scroll->setOverscrollDefaults(
expanded ? -st::dialogsStoriesFull.height : 0,
0);
}, lifetime());
}
void Widget::setupShortcuts() { void Widget::setupShortcuts() {
Shortcuts::Requests( Shortcuts::Requests(
) | rpl::filter([=] { ) | rpl::filter([=] {
@ -1128,7 +1171,7 @@ void Widget::jumpToTop(bool belowPinned) {
return; return;
} }
if ((currentSearchQuery().trimmed().isEmpty() && !_searchInChat)) { if ((currentSearchQuery().trimmed().isEmpty() && !_searchInChat)) {
auto to = _inner->defaultScrollTop(); auto to = 0;
if (belowPinned) { if (belowPinned) {
const auto list = _openedForum const auto list = _openedForum
? _openedForum->topicsList() ? _openedForum->topicsList()
@ -1156,7 +1199,7 @@ void Widget::scrollToDefault(bool verytop) {
} }
_scrollToAnimation.stop(); _scrollToAnimation.stop();
auto scrollTop = _scroll->scrollTop(); auto scrollTop = _scroll->scrollTop();
const auto scrollTo = verytop ? 0 : _inner->defaultScrollTop(); const auto scrollTo = 0;
if (scrollTop == scrollTo) { if (scrollTop == scrollTo) {
return; return;
} }
@ -1172,7 +1215,7 @@ void Widget::scrollToDefault(bool verytop) {
const auto animated = qRound(_scrollToAnimation.value(scrollTo)); const auto animated = qRound(_scrollToAnimation.value(scrollTo));
const auto animatedDelta = animated - scrollTo; const auto animatedDelta = animated - scrollTo;
const auto realDelta = _scroll->scrollTop() - scrollTo; const auto realDelta = _scroll->scrollTop() - scrollTo;
if (realDelta * animatedDelta < 0) { if (base::OppositeSigns(realDelta, animatedDelta)) {
// We scrolled manually to the other side of target 'scrollTo'. // We scrolled manually to the other side of target 'scrollTo'.
_scrollToAnimation.stop(); _scrollToAnimation.stop();
} else if (std::abs(realDelta) > std::abs(animatedDelta)) { } else if (std::abs(realDelta) > std::abs(animatedDelta)) {
@ -1181,6 +1224,7 @@ void Widget::scrollToDefault(bool verytop) {
} }
}; };
_scrollAnimationTo = scrollTo;
_scrollToAnimation.start( _scrollToAnimation.start(
scroll, scroll,
scrollTop, scrollTop,
@ -2398,55 +2442,6 @@ void Widget::completeHashtag(QString tag) {
applyFilterUpdate(true); applyFilterUpdate(true);
} }
bool Widget::customWheelProcess(not_null<QWheelEvent*> e) {
customScrollProcess(e->phase());
return false;
}
void Widget::customScrollProcess(Qt::ScrollPhase phase) {
const auto now = _scroll->scrollTop();
const auto def = _inner->defaultScrollTop();
//const auto bar = _scroll->verticalScrollBar();
if (phase == Qt::ScrollBegin || phase == Qt::ScrollUpdate) {
_allowStoriesExpandTimer.cancel();
_inner->setTouchScrollActive(true);
//bar->setMinimum(0);
} else if (phase == Qt::ScrollEnd || phase == Qt::ScrollMomentum) {
_allowStoriesExpandTimer.cancel();
_inner->setTouchScrollActive(false);
if (def > 0 && now >= def) {
//bar->setMinimum(def);
} else {
//bar->setMinimum(0);
}
} else {
const auto allow = (def <= 0)
|| (now < def)
|| (now == def && !_allowStoriesExpandTimer.isActive());
if (allow) {
//_scroll->verticalScrollBar()->setMinimum(0);
_allowStoriesExpandTimer.cancel();
} else {
//bar->setMinimum(def);
_allowStoriesExpandTimer.callOnce(kWaitTillAllowStoriesExpand);
}
}
}
bool Widget::customTouchProcess(not_null<QTouchEvent*> e) {
const auto type = e->type();
customScrollProcess([&] {
switch (e->type()) {
case QEvent::TouchBegin: return Qt::ScrollBegin;
case QEvent::TouchUpdate: return Qt::ScrollUpdate;
case QEvent::TouchEnd:
case QEvent::TouchCancel: return Qt::ScrollEnd;
}
Unexpected("Touch event type in Widdget::customTouchProcess.");
}());
return false;
}
void Widget::resizeEvent(QResizeEvent *e) { void Widget::resizeEvent(QResizeEvent *e) {
updateControlsGeometry(); updateControlsGeometry();
} }
@ -2526,11 +2521,9 @@ void Widget::updateControlsGeometry() {
? st::dialogsFilterSkip ? st::dialogsFilterSkip
: (st::dialogsFilterPadding.x() + _mainMenu.toggle->width())) : (st::dialogsFilterPadding.x() + _mainMenu.toggle->width()))
+ st::dialogsFilterPadding.x(); + st::dialogsFilterPadding.x();
auto filterRight = (session().domain().local().hasLocalPasscode() const auto filterRight = st::dialogsFilterSkip + st::dialogsFilterPadding.x();
? (st::dialogsFilterPadding.x() + _lockUnlock->width()) const auto filterWidth = qMax(ratiow, smallw) - filterLeft - filterRight;
: st::dialogsFilterSkip) + st::dialogsFilterPadding.x(); const auto filterAreaHeight = st::topBarHeight;
auto filterWidth = qMax(ratiow, smallw) - filterLeft - filterRight;
auto filterAreaHeight = st::topBarHeight;
_searchControls->setGeometry(0, filterAreaTop, ratiow, filterAreaHeight); _searchControls->setGeometry(0, filterAreaTop, ratiow, filterAreaHeight);
if (_subsectionTopBar) { if (_subsectionTopBar) {
_subsectionTopBar->setGeometryWithNarrowRatio( _subsectionTopBar->setGeometryWithNarrowRatio(
@ -2542,6 +2535,7 @@ void Widget::updateControlsGeometry() {
auto filterTop = (filterAreaHeight - _filter->height()) / 2; auto filterTop = (filterAreaHeight - _filter->height()) / 2;
filterLeft = anim::interpolate(filterLeft, _narrowWidth, narrowRatio); filterLeft = anim::interpolate(filterLeft, _narrowWidth, narrowRatio);
_filter->setGeometryToLeft(filterLeft, filterTop, filterWidth, _filter->height()); _filter->setGeometryToLeft(filterLeft, filterTop, filterWidth, _filter->height());
auto mainMenuLeft = anim::interpolate( auto mainMenuLeft = anim::interpolate(
st::dialogsFilterPadding.x(), st::dialogsFilterPadding.x(),
(_narrowWidth - _mainMenu.toggle->width()) / 2, (_narrowWidth - _mainMenu.toggle->width()) / 2,
@ -2567,14 +2561,21 @@ void Widget::updateControlsGeometry() {
right -= _chooseFromUser->width(); _chooseFromUser->moveToLeft(right, _filter->y()); right -= _chooseFromUser->width(); _chooseFromUser->moveToLeft(right, _filter->y());
const auto barw = width(); const auto barw = width();
const auto expandedStoriesTop = filterAreaTop + filterAreaHeight;
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 (_forumTopShadow) { if (_forumTopShadow) {
_forumTopShadow->setGeometry( _forumTopShadow->setGeometry(
0, 0,
filterAreaTop + filterAreaHeight, expandedStoriesTop,
barw, barw,
st::lineWidth); st::lineWidth);
} }
const auto moreChatsBarTop = filterAreaTop + filterAreaHeight; const auto moreChatsBarTop = expandedStoriesTop + _overscrollTop;
if (_moreChatsBar) { if (_moreChatsBar) {
_moreChatsBar->move(0, moreChatsBarTop); _moreChatsBar->move(0, moreChatsBarTop);
_moreChatsBar->resizeToWidth(barw); _moreChatsBar->resizeToWidth(barw);
@ -2599,8 +2600,7 @@ void Widget::updateControlsGeometry() {
auto scrollTop = forumReportTop auto scrollTop = forumReportTop
+ (_forumReportBar ? _forumReportBar->bar().height() : 0); + (_forumReportBar ? _forumReportBar->bar().height() : 0);
const auto wasScrollTop = _scroll->scrollTop(); const auto wasScrollTop = _scroll->scrollTop();
const auto newScrollTop = (_topDelta < 0 const auto newScrollTop = (_topDelta < 0 && wasScrollTop <= 0)
&& wasScrollTop <= _inner->defaultScrollTop())
? wasScrollTop ? wasScrollTop
: (wasScrollTop + _topDelta); : (wasScrollTop + _topDelta);
auto scrollHeight = height() - scrollTop; auto scrollHeight = height() - scrollTop;
@ -2626,19 +2626,13 @@ void Widget::updateControlsGeometry() {
const auto scrollw = _childList ? _narrowWidth : barw; const auto scrollw = _childList ? _narrowWidth : barw;
const auto wasScrollHeight = _scroll->height(); const auto wasScrollHeight = _scroll->height();
if (scrollHeight >= wasScrollHeight) {
_inner->setViewportHeight(scrollHeight);
}
_scroll->setGeometry(0, scrollTop, scrollw, scrollHeight); _scroll->setGeometry(0, scrollTop, scrollw, scrollHeight);
if (scrollHeight < wasScrollHeight) {
_inner->setViewportHeight(scrollHeight);
}
_inner->resize(scrollw, _inner->height()); _inner->resize(scrollw, _inner->height());
_inner->setNarrowRatio(narrowRatio); _inner->setNarrowRatio(narrowRatio);
if (scrollHeight != wasScrollHeight) { if (scrollHeight != wasScrollHeight) {
controller()->floatPlayerAreaUpdated(); controller()->floatPlayerAreaUpdated();
} }
const auto startWithTop = _inner->defaultScrollTop(); const auto startWithTop = 0;
if (wasScrollHeight < startWithTop && scrollHeight >= startWithTop) { if (wasScrollHeight < startWithTop && scrollHeight >= startWithTop) {
_scroll->scrollToY(startWithTop); _scroll->scrollToY(startWithTop);
} else if (newScrollTop != wasScrollTop) { } else if (newScrollTop != wasScrollTop) {
@ -2718,7 +2712,7 @@ void Widget::paintEvent(QPaintEvent *e) {
p.fillRect(above.intersected(r), bg); p.fillRect(above.intersected(r), bg);
} }
auto belowTop = _scroll->y() + qMin(_scroll->height(), _inner->height()); auto belowTop = _scroll->y() + _scroll->height();
if (!_widthAnimationCache.isNull()) { if (!_widthAnimationCache.isNull()) {
p.drawPixmapLeft(0, _scroll->y(), width(), _widthAnimationCache); p.drawPixmapLeft(0, _scroll->y(), width(), _widthAnimationCache);
belowTop = _scroll->y() + (_widthAnimationCache.height() / cIntRetinaFactor()); belowTop = _scroll->y() + (_widthAnimationCache.height() / cIntRetinaFactor());

View File

@ -56,6 +56,10 @@ class ConnectionState;
struct SectionShow; struct SectionShow;
} // namespace Window } // namespace Window
namespace Dialogs::Stories {
class List;
} // namespace Dialogs::Stories
namespace Dialogs { namespace Dialogs {
struct RowDescriptor; struct RowDescriptor;
@ -136,9 +140,6 @@ private:
void cancelSearchInChat(); void cancelSearchInChat();
void filterCursorMoved(); void filterCursorMoved();
void completeHashtag(QString tag); void completeHashtag(QString tag);
bool customWheelProcess(not_null<QWheelEvent*> e);
bool customTouchProcess(not_null<QTouchEvent*> e);
void customScrollProcess(Qt::ScrollPhase phase);
[[nodiscard]] QString currentSearchQuery() const; [[nodiscard]] QString currentSearchQuery() const;
void clearSearchField(); void clearSearchField();
@ -165,6 +166,7 @@ private:
void setupMoreChatsBar(); void setupMoreChatsBar();
void setupDownloadBar(); void setupDownloadBar();
void setupShortcuts(); void setupShortcuts();
void setupStories();
[[nodiscard]] bool searchForPeersRequired(const QString &query) const; [[nodiscard]] bool searchForPeersRequired(const QString &query) const;
[[nodiscard]] bool searchForTopicsRequired(const QString &query) const; [[nodiscard]] bool searchForTopicsRequired(const QString &query) const;
bool setSearchInChat(Key chat, PeerData *from = nullptr); bool setSearchInChat(Key chat, PeerData *from = nullptr);
@ -248,7 +250,6 @@ private:
std::unique_ptr<HistoryView::ContactStatus> _forumReportBar; std::unique_ptr<HistoryView::ContactStatus> _forumReportBar;
object_ptr<Ui::ElasticScroll> _scroll; object_ptr<Ui::ElasticScroll> _scroll;
base::Timer _allowStoriesExpandTimer;
QPointer<InnerWidget> _inner; QPointer<InnerWidget> _inner;
class BottomButton; class BottomButton;
object_ptr<BottomButton> _updateTelegram = { nullptr }; object_ptr<BottomButton> _updateTelegram = { nullptr };
@ -257,6 +258,7 @@ private:
std::unique_ptr<Window::ConnectionState> _connecting; std::unique_ptr<Window::ConnectionState> _connecting;
Ui::Animations::Simple _scrollToAnimation; Ui::Animations::Simple _scrollToAnimation;
int _scrollAnimationTo = 0;
std::unique_ptr<Window::SlideAnimation> _showAnimation; std::unique_ptr<Window::SlideAnimation> _showAnimation;
rpl::variable<float64> _shownProgressValue; rpl::variable<float64> _shownProgressValue;
@ -265,6 +267,9 @@ private:
bool _scrollToTopIsShown = false; bool _scrollToTopIsShown = false;
bool _forumSearchRequested = false; bool _forumSearchRequested = false;
int _overscrollTop = 0;
std::unique_ptr<Stories::List> _stories;
Data::Folder *_openedFolder = nullptr; Data::Folder *_openedFolder = nullptr;
Data::Forum *_openedForum = nullptr; Data::Forum *_openedForum = nullptr;
Dialogs::Key _searchInChat; Dialogs::Key _searchInChat;

View File

@ -24,7 +24,7 @@ constexpr auto kPreloadPages = 2;
constexpr auto kExpandAfterRatio = 0.85; constexpr auto kExpandAfterRatio = 0.85;
constexpr auto kCollapseAfterRatio = 0.72; constexpr auto kCollapseAfterRatio = 0.72;
constexpr auto kFrictionRatio = 0.15; constexpr auto kFrictionRatio = 0.15;
constexpr auto kSnapExpandedTimeout = crl::time(200); constexpr auto kExpandCatchUpDuration = crl::time(200);
[[nodiscard]] int AvailableNameWidth(const style::DialogsStoriesList &st) { [[nodiscard]] int AvailableNameWidth(const style::DialogsStoriesList &st) {
const auto &full = st.full; const auto &full = st.full;
@ -37,7 +37,6 @@ constexpr auto kSnapExpandedTimeout = crl::time(200);
struct List::Layout { struct List::Layout {
int itemsCount = 0; int itemsCount = 0;
int shownHeight = 0;
float64 expandedRatio = 0.; float64 expandedRatio = 0.;
float64 ratio = 0.; float64 ratio = 0.;
float64 thumbnailLeft = 0.; float64 thumbnailLeft = 0.;
@ -58,12 +57,9 @@ struct List::Layout {
List::List( List::List(
not_null<QWidget*> parent, not_null<QWidget*> parent,
const style::DialogsStoriesList &st, const style::DialogsStoriesList &st,
rpl::producer<Content> content, rpl::producer<Content> content)
Fn<int()> shownHeight)
: RpWidget(parent) : RpWidget(parent)
, _st(st) , _st(st) {
, _shownHeight(shownHeight)
, _snapExpandedTimer([=] { requestExpanded(_expanded); }) {
setCursor(style::cur_default); setCursor(style::cur_default);
std::move(content) | rpl::start_with_next([=](Content &&content) { std::move(content) | rpl::start_with_next([=](Content &&content) {
@ -87,6 +83,7 @@ void List::showContent(Content &&content) {
return; return;
} }
const auto hidden = _content.elements.empty(); const auto hidden = _content.elements.empty();
const auto wasCount = int((hidden ? _hidingData : _data).items.size());
_content = std::move(content); _content = std::move(content);
auto items = base::take( auto items = base::take(
_data.items.empty() ? _hidingData.items : _data.items); _data.items.empty() ? _hidingData.items : _data.items);
@ -114,6 +111,9 @@ void List::showContent(Content &&content) {
_data.items.emplace_back(Item{ .element = element }); _data.items.emplace_back(Item{ .element = element });
} }
} }
if (int(_data.items.size()) != wasCount) {
updateGeometry();
}
updateScrollMax(); updateScrollMax();
updateSummary(_data); updateSummary(_data);
update(); update();
@ -253,7 +253,6 @@ rpl::producer<> List::loadMoreRequests() const {
} }
void List::requestExpanded(bool expanded) { void List::requestExpanded(bool expanded) {
_snapExpandedTimer.cancel();
if (_expanded != expanded) { if (_expanded != expanded) {
_expanded = expanded; _expanded = expanded;
_expandedAnimation.start( _expandedAnimation.start(
@ -274,12 +273,12 @@ void List::resizeEvent(QResizeEvent *e) {
updateScrollMax(); updateScrollMax();
} }
void List::updateExpanding(int minHeight, int shownHeight, int fullHeight) { void List::updateExpanding(int expandingHeight, int expandedHeight) {
Expects(shownHeight == minHeight || fullHeight > minHeight); Expects(!expandingHeight || expandedHeight > 0);
const auto ratio = (shownHeight == minHeight) const auto ratio = !expandingHeight
? 0. ? 0.
: (float64(shownHeight - minHeight) / (fullHeight - minHeight)); : (float64(expandingHeight) / expandedHeight);
if (_lastRatio == ratio) { if (_lastRatio == ratio) {
return; return;
} }
@ -296,20 +295,12 @@ void List::updateExpanding(int minHeight, int shownHeight, int fullHeight) {
List::Layout List::computeLayout() { List::Layout List::computeLayout() {
const auto &st = _st.small; const auto &st = _st.small;
const auto &full = _st.full; const auto &full = _st.full;
const auto shownHeight = std::max(_shownHeight(), st.height); const auto use = _lastExpandedHeight
if (_lastHeight != shownHeight) { * _expandCatchUpAnimation.value(1.);
_lastHeight = shownHeight; updateExpanding(use, full.height);
if (_lastHeight == st.height || _lastHeight == full.height) {
_snapExpandedTimer.cancel();
} else if (!_touchScrollActive) {
_snapExpandedTimer.callOnce(kSnapExpandedTimeout);
}
}
updateExpanding(st.height, shownHeight, full.height);
const auto expanded = _expandedAnimation.value(_expanded ? 1. : 0.); const auto expanded = _expandedAnimation.value(_expanded ? 1. : 0.);
const auto expandedRatio = float64(shownHeight - st.height) const auto expandedRatio = _lastRatio;
/ (full.height - st.height);
const auto collapsedRatio = expandedRatio * kFrictionRatio; const auto collapsedRatio = expandedRatio * kFrictionRatio;
const auto ratio = expandedRatio * expanded const auto ratio = expandedRatio * expanded
+ collapsedRatio * (1. - expanded); + collapsedRatio * (1. - expanded);
@ -323,7 +314,7 @@ List::Layout List::computeLayout() {
const auto narrowWidth = st::defaultDialogRow.padding.left() const auto narrowWidth = st::defaultDialogRow.padding.left()
+ st::defaultDialogRow.photoSize + st::defaultDialogRow.photoSize
+ st::defaultDialogRow.padding.left(); + st::defaultDialogRow.padding.left();
const auto narrow = (width() <= narrowWidth); const auto narrow = false;// (width() <= narrowWidth);
const auto smallSkip = (itemsCount > 1 const auto smallSkip = (itemsCount > 1
&& rendering.items[0].element.skipSmall) && rendering.items[0].element.skipSmall)
? 1 ? 1
@ -352,7 +343,6 @@ List::Layout List::computeLayout() {
const auto photoLeft = lerp(st.photoLeft, full.photoLeft); const auto photoLeft = lerp(st.photoLeft, full.photoLeft);
return Layout{ return Layout{
.itemsCount = itemsCount, .itemsCount = itemsCount,
.shownHeight = shownHeight,
.expandedRatio = expandedRatio, .expandedRatio = expandedRatio,
.ratio = ratio, .ratio = ratio,
.thumbnailLeft = thumbnailLeft, .thumbnailLeft = thumbnailLeft,
@ -391,14 +381,14 @@ void List::paintEvent(QPaintEvent *e) {
auto &rendering = _data.empty() ? _hidingData : _data; auto &rendering = _data.empty() ? _hidingData : _data;
const auto line = elerp(st.lineTwice, full.lineTwice) / 2.; const auto line = elerp(st.lineTwice, full.lineTwice) / 2.;
const auto lineRead = elerp(st.lineReadTwice, full.lineReadTwice) / 2.; const auto lineRead = elerp(st.lineReadTwice, full.lineReadTwice) / 2.;
const auto photoTopSmall = (st.height - st.photo) / 2.; const auto photoTopSmall = st.photoTop;
const auto photoTop = photoTopSmall const auto photoTop = photoTopSmall
+ (full.photoTop - photoTopSmall) * layout.expandedRatio; + (full.photoTop - photoTopSmall) * layout.expandedRatio;
const auto photo = lerp(st.photo, full.photo); const auto photo = lerp(st.photo, full.photo);
const auto summaryTop = st.nameTop const auto summaryTop = st.nameTop
- (st.photoTop + (st.photo / 2.)) - (st.photoTop + (st.photo / 2.))
+ (photoTop + (photo / 2.)); + (photoTop + (photo / 2.));
const auto nameScale = layout.shownHeight / float64(full.height); const auto nameScale = _lastRatio;
const auto nameTop = nameScale * full.nameTop; const auto nameTop = nameScale * full.nameTop;
const auto nameWidth = nameScale * AvailableNameWidth(_st); const auto nameWidth = nameScale * AvailableNameWidth(_st);
const auto nameHeight = nameScale * full.nameStyle.font->height; const auto nameHeight = nameScale * full.nameStyle.font->height;
@ -407,8 +397,18 @@ void List::paintEvent(QPaintEvent *e) {
const auto readUserpicAppearingOpacity = elerp(_st.readOpacity, 0.); const auto readUserpicAppearingOpacity = elerp(_st.readOpacity, 0.);
auto p = QPainter(this); auto p = QPainter(this);
p.fillRect(e->rect(), _bgOverride.value_or(_st.bg));
p.translate(0, height() - layout.shownHeight); if (_state == State::Changing) {
const auto left = anim::interpolate(
_changingGeometryFrom.x(),
_geometryFull.x(),
layout.expandedRatio);
const auto top = anim::interpolate(
_changingGeometryFrom.y(),
_geometryFull.y(),
layout.expandedRatio);
p.translate(QPoint(left, top) - pos());
}
const auto drawSmall = (expandRatio < 1.); const auto drawSmall = (expandRatio < 1.);
const auto drawFull = (expandRatio > 0.); const auto drawFull = (expandRatio > 0.);
@ -691,6 +691,7 @@ void List::paintSummary(
Data &data, Data &data,
float64 summaryTop, float64 summaryTop,
float64 hidden) { float64 hidden) {
#if 0 // #TODO stories to-remove
const auto total = int(data.items.size()); const auto total = int(data.items.size());
auto &summary = ChooseSummary( auto &summary = ChooseSummary(
_st.small, _st.small,
@ -723,6 +724,7 @@ void List::paintSummary(
p.drawImage( p.drawImage(
QRectF(left, summaryTop, summaryWidth, summaryHeight), QRectF(left, summaryTop, summaryWidth, summaryHeight),
summary.cache); summary.cache);
#endif
} }
void List::wheelEvent(QWheelEvent *e) { void List::wheelEvent(QWheelEvent *e) {
@ -767,12 +769,9 @@ void List::mouseMoveEvent(QMouseEvent *e) {
_lastMousePosition = e->globalPos(); _lastMousePosition = e->globalPos();
updateSelected(); updateSelected();
if (!_dragging && _mouseDownPosition) { if (!_dragging && _mouseDownPosition && _state == State::Full) {
if ((_lastMousePosition - *_mouseDownPosition).manhattanLength() if ((_lastMousePosition - *_mouseDownPosition).manhattanLength()
>= QApplication::startDragDistance()) { >= QApplication::startDragDistance()) {
if (_shownHeight() < _st.full.height) {
requestExpanded(true);
}
_dragging = true; _dragging = true;
_startDraggingLeft = _scrollLeft; _startDraggingLeft = _scrollLeft;
} }
@ -822,19 +821,82 @@ void List::mouseReleaseEvent(QMouseEvent *e) {
} }
} }
void List::setBgOverride(QBrush brush) { void List::setExpandedHeight(int height, bool momentum) {
_bgOverride = std::move(brush); height = std::clamp(height, 0, _st.full.height);
if (_lastExpandedHeight == height) {
return;
} else if (momentum && _expandIgnored) {
return;
} else if (momentum && height > 0 && !_lastExpandedHeight) {
_expandIgnored = true;
return;
} else if (!momentum && _expandIgnored && height > 0) {
_expandIgnored = false;
_expandCatchUpAnimation.start([=] {
update();
if (!_expandCatchUpAnimation.animating()
&& _lastExpandedHeight == _st.full.height) {
setState(State::Full);
}
}, 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);
update();
} }
void List::setTouchScrollActive(bool active) { void List::setLayoutConstraints(QPoint topRightSmall, QRect geometryFull) {
if (_touchScrollActive != active) { _topRightSmall = topRightSmall;
_touchScrollActive = active; _geometryFull = geometryFull;
if (active) { updateGeometry();
_snapExpandedTimer.cancel(); update();
} else { }
requestExpanded(_expanded);
} void List::updateGeometry() {
switch (_state) {
case State::Small: setGeometry(countSmallGeometry()); break;
case State::Changing: {
_changingGeometryFrom = countSmallGeometry();
setGeometry(_geometryFull.united(_changingGeometryFrom));
} break;
case State::Full: setGeometry(_geometryFull);
} }
update();
}
QRect List::countSmallGeometry() const {
const auto &st = _st.small;
const auto layout = const_cast<List*>(this)->computeLayout();
const auto count = layout.endIndexSmall - layout.startIndexSmall;
const auto width = st.left
+ st.photoLeft
+ st.photo + (count - 1) * st.shift
+ st.photoLeft
+ st.left;
return QRect(
_topRightSmall.x() - width,
_topRightSmall.y(),
width,
st.photoTop + st.photo + st.photoTop);
}
void List::setState(State state) {
if (_state == state) {
return;
}
_state = state;
setAttribute(
Qt::WA_TransparentForMouseEvents,
state == State::Changing);
updateGeometry();
} }
void List::contextMenuEvent(QContextMenuEvent *e) { void List::contextMenuEvent(QContextMenuEvent *e) {

View File

@ -63,11 +63,10 @@ public:
List( List(
not_null<QWidget*> parent, not_null<QWidget*> parent,
const style::DialogsStoriesList &st, const style::DialogsStoriesList &st,
rpl::producer<Content> content, rpl::producer<Content> content);
Fn<int()> shownHeight);
void setBgOverride(QBrush brush); void setExpandedHeight(int height, bool momentum = false);
void setTouchScrollActive(bool active); void setLayoutConstraints(QPoint topRightSmall, QRect geometryFull);
[[nodiscard]] rpl::producer<uint64> clicks() const; [[nodiscard]] rpl::producer<uint64> clicks() const;
[[nodiscard]] rpl::producer<ShowMenuRequest> showMenuRequests() const; [[nodiscard]] rpl::producer<ShowMenuRequest> showMenuRequests() const;
@ -77,6 +76,11 @@ public:
private: private:
struct Layout; struct Layout;
enum class State {
Small,
Changing,
Full,
};
struct Item { struct Item {
Element element; Element element;
QImage nameCache; QImage nameCache;
@ -149,7 +153,10 @@ private:
void checkLoadMore(); void checkLoadMore();
void requestExpanded(bool expanded); void requestExpanded(bool expanded);
void updateExpanding(int minHeight, int shownHeight, int fullHeight); void setState(State state);
void updateGeometry();
[[nodiscard]] QRect countSmallGeometry() const;
void updateExpanding(int expandingHeight, int expandedHeight);
void updateHeight(); void updateHeight();
void toggleAnimated(bool shown); void toggleAnimated(bool shown);
void paintSummary( void paintSummary(
@ -164,14 +171,17 @@ private:
Content _content; Content _content;
Data _data; Data _data;
Data _hidingData; Data _hidingData;
Fn<int()> _shownHeight = 0;
rpl::event_stream<uint64> _clicks; rpl::event_stream<uint64> _clicks;
rpl::event_stream<ShowMenuRequest> _showMenuRequests; rpl::event_stream<ShowMenuRequest> _showMenuRequests;
rpl::event_stream<bool> _toggleExpandedRequests; rpl::event_stream<bool> _toggleExpandedRequests;
rpl::event_stream<> _entered; rpl::event_stream<> _entered;
rpl::event_stream<> _loadMoreRequests; rpl::event_stream<> _loadMoreRequests;
std::optional<QBrush> _bgOverride; QPoint _topRightSmall;
QRect _geometryFull;
QRect _changingGeometryFrom;
State _state = State::Small;
Ui::Animations::Simple _shownAnimation; Ui::Animations::Simple _shownAnimation;
QPoint _lastMousePosition; QPoint _lastMousePosition;
@ -182,11 +192,11 @@ private:
bool _dragging = false; bool _dragging = false;
Ui::Animations::Simple _expandedAnimation; Ui::Animations::Simple _expandedAnimation;
base::Timer _snapExpandedTimer; Ui::Animations::Simple _expandCatchUpAnimation;
float64 _lastRatio = 0.; float64 _lastRatio = 0.;
int _lastHeight = 0; int _lastExpandedHeight = 0;
bool _expanded = false; bool _expandIgnored : 1 = false;
bool _touchScrollActive = false; bool _expanded : 1 = false;
int _selected = -1; int _selected = -1;
int _pressed = -1; int _pressed = -1;

View File

@ -465,8 +465,7 @@ void TopBar::setStories(rpl::producer<Dialogs::Stories::Content> content) {
last last
) | rpl::filter([](const Content &content) { ) | rpl::filter([](const Content &content) {
return !content.elements.empty(); return !content.elements.empty();
}), })),
[] { return st::dialogsStories.height; }),
st::infoTopBarScale); st::infoTopBarScale);
registerToggleControlCallback( registerToggleControlCallback(
stories, stories,

View File

@ -170,8 +170,7 @@ void InnerWidget::createButtons() {
st::dialogsStoriesListMine, st::dialogsStoriesListMine,
rpl::duplicate(last) | rpl::filter([](const Content &content) { rpl::duplicate(last) | rpl::filter([](const Content &content) {
return !content.elements.empty(); return !content.elements.empty();
}), }));
[] { return st::dialogsStories.height; });
thumbs->show(); thumbs->show();
rpl::combine( rpl::combine(
recent->sizeValue(), recent->sizeValue(),

@ -1 +1 @@
Subproject commit 7135f3ed87ee1a6d89cebe6510a2250ffedfb1a9 Subproject commit 80308cea4f57fd13e73abec121325f174ba21883