mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-30 15:30:20 +00:00
Save scroll top state to media memento.
This commit is contained in:
parent
f6ed3dff7f
commit
15cc4502b4
@ -150,7 +150,7 @@ infoLayerTopBar: InfoTopBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
infoMinimalWidth: 324px;
|
infoMinimalWidth: 324px;
|
||||||
infoDesiredWidth: 360px;
|
infoDesiredWidth: 430px;
|
||||||
infoMinimalLayerMargin: 48px;
|
infoMinimalLayerMargin: 48px;
|
||||||
|
|
||||||
infoTabs: SettingsSlider(defaultTabsSlider) {
|
infoTabs: SettingsSlider(defaultTabsSlider) {
|
||||||
|
@ -57,6 +57,10 @@ ContentWidget::ContentWidget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContentWidget::resizeEvent(QResizeEvent *e) {
|
void ContentWidget::resizeEvent(QResizeEvent *e) {
|
||||||
|
updateControlsGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContentWidget::updateControlsGeometry() {
|
||||||
auto newScrollTop = _scroll->scrollTop() + _topDelta;
|
auto newScrollTop = _scroll->scrollTop() + _topDelta;
|
||||||
auto scrollGeometry = rect().marginsRemoved(
|
auto scrollGeometry = rect().marginsRemoved(
|
||||||
QMargins(0, _scrollTopSkip, 0, 0));
|
QMargins(0, _scrollTopSkip, 0, 0));
|
||||||
@ -113,6 +117,10 @@ Ui::RpWidget *ContentWidget::doSetInnerWidget(
|
|||||||
int desired) {
|
int desired) {
|
||||||
inner->setVisibleTopBottom(top, bottom);
|
inner->setVisibleTopBottom(top, bottom);
|
||||||
}, _inner->lifetime());
|
}, _inner->lifetime());
|
||||||
|
|
||||||
|
_scrollTopSkip = scrollTopSkip;
|
||||||
|
updateControlsGeometry();
|
||||||
|
|
||||||
return _inner;
|
return _inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ private:
|
|||||||
RpWidget *doSetInnerWidget(
|
RpWidget *doSetInnerWidget(
|
||||||
object_ptr<RpWidget> inner,
|
object_ptr<RpWidget> inner,
|
||||||
int scrollTopSkip);
|
int scrollTopSkip);
|
||||||
|
void updateControlsGeometry();
|
||||||
|
|
||||||
const not_null<Window::Controller*> _controller;
|
const not_null<Window::Controller*> _controller;
|
||||||
const not_null<PeerData*> _peer;
|
const not_null<PeerData*> _peer;
|
||||||
|
@ -252,9 +252,11 @@ object_ptr<ListWidget> InnerWidget::setupList(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::saveState(not_null<Memento*> memento) {
|
void InnerWidget::saveState(not_null<Memento*> memento) {
|
||||||
|
_list->saveState(memento);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::restoreState(not_null<Memento*> memento) {
|
void InnerWidget::restoreState(not_null<Memento*> memento) {
|
||||||
|
_list->restoreState(memento);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<SelectedItems> InnerWidget::selectedListValue() const {
|
rpl::producer<SelectedItems> InnerWidget::selectedListValue() const {
|
||||||
|
@ -720,6 +720,12 @@ bool ListWidget::isMyItem(not_null<const HistoryItem*> item) const {
|
|||||||
return (_peer == peer || _peer == peer->migrateTo());
|
return (_peer == peer || _peer == peer->migrateTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ListWidget::isPossiblyMyId(FullMsgId fullId) const {
|
||||||
|
return (fullId.channel != 0)
|
||||||
|
? (_peer->isChannel() && _peer->bareId() == fullId.channel)
|
||||||
|
: (!_peer->isChannel() || _peer->migrateFrom());
|
||||||
|
}
|
||||||
|
|
||||||
bool ListWidget::isItemLayout(
|
bool ListWidget::isItemLayout(
|
||||||
not_null<const HistoryItem*> item,
|
not_null<const HistoryItem*> item,
|
||||||
BaseLayout *layout) const {
|
BaseLayout *layout) const {
|
||||||
@ -878,6 +884,29 @@ void ListWidget::markLayoutsStale() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::saveState(not_null<Memento*> memento) {
|
||||||
|
if (_universalAroundId != kDefaultAroundId) {
|
||||||
|
memento->setAroundId(computeFullId(_universalAroundId));
|
||||||
|
memento->setIdsLimit(_idsLimit);
|
||||||
|
auto state = countScrollState();
|
||||||
|
memento->setScrollTopItem(computeFullId(state.item));
|
||||||
|
memento->setScrollTopShift(state.shift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::restoreState(not_null<Memento*> memento) {
|
||||||
|
if (auto limit = memento->idsLimit()) {
|
||||||
|
auto wasAroundId = memento->aroundId();
|
||||||
|
if (isPossiblyMyId(wasAroundId)) {
|
||||||
|
_idsLimit = limit;
|
||||||
|
_universalAroundId = GetUniversalId(wasAroundId);
|
||||||
|
_scrollTopState.item = GetUniversalId(memento->scrollTopItem());
|
||||||
|
_scrollTopState.shift = memento->scrollTopShift();
|
||||||
|
refreshViewer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ListWidget::resizeGetHeight(int newWidth) {
|
int ListWidget::resizeGetHeight(int newWidth) {
|
||||||
if (newWidth > 0) {
|
if (newWidth > 0) {
|
||||||
for (auto §ion : _sections) {
|
for (auto §ion : _sections) {
|
||||||
@ -887,7 +916,7 @@ int ListWidget::resizeGetHeight(int newWidth) {
|
|||||||
return recountHeight();
|
return recountHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ListWidget::findItemByPoint(QPoint point) -> FoundItem {
|
auto ListWidget::findItemByPoint(QPoint point) const -> FoundItem {
|
||||||
Expects(!_sections.empty());
|
Expects(!_sections.empty());
|
||||||
auto sectionIt = findSectionAfterTop(point.y());
|
auto sectionIt = findSectionAfterTop(point.y());
|
||||||
if (sectionIt == _sections.end()) {
|
if (sectionIt == _sections.end()) {
|
||||||
@ -920,7 +949,7 @@ auto ListWidget::findItemDetails(
|
|||||||
|
|
||||||
auto ListWidget::foundItemInSection(
|
auto ListWidget::foundItemInSection(
|
||||||
const FoundItem &item,
|
const FoundItem &item,
|
||||||
const Section §ion) -> FoundItem {
|
const Section §ion) const -> FoundItem {
|
||||||
return {
|
return {
|
||||||
item.layout,
|
item.layout,
|
||||||
item.geometry.translated(0, section.top()),
|
item.geometry.translated(0, section.top()),
|
||||||
@ -941,7 +970,7 @@ void ListWidget::checkMoveToOtherViewer() {
|
|||||||
if (width() <= 0
|
if (width() <= 0
|
||||||
|| visibleHeight <= 0
|
|| visibleHeight <= 0
|
||||||
|| _sections.empty()
|
|| _sections.empty()
|
||||||
|| _scrollTopId) {
|
|| _scrollTopState.item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -994,34 +1023,39 @@ void ListWidget::checkMoveToOtherViewer() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::saveScrollState() {
|
auto ListWidget::countScrollState() const -> ScrollTopState {
|
||||||
if (_sections.empty()) {
|
if (_sections.empty()) {
|
||||||
_scrollTopId = 0;
|
return { 0, 0 };
|
||||||
_scrollTopShift = 0;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
auto topItem = findItemByPoint({ 0, _visibleTop });
|
auto topItem = findItemByPoint({ 0, _visibleTop });
|
||||||
_scrollTopId = GetUniversalId(topItem.layout);
|
return {
|
||||||
_scrollTopShift = _visibleTop - topItem.geometry.y();
|
GetUniversalId(topItem.layout),
|
||||||
|
_visibleTop - topItem.geometry.y()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::saveScrollState() {
|
||||||
|
if (!_scrollTopState.item) {
|
||||||
|
_scrollTopState = countScrollState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::restoreScrollState() {
|
void ListWidget::restoreScrollState() {
|
||||||
auto scrollTopId = base::take(_scrollTopId);
|
if (_sections.empty() || !_scrollTopState.item) {
|
||||||
auto scrollTopShift = base::take(_scrollTopShift);
|
|
||||||
if (_sections.empty() || !scrollTopId) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto sectionIt = findSectionByItem(scrollTopId);
|
auto sectionIt = findSectionByItem(_scrollTopState.item);
|
||||||
if (sectionIt == _sections.end()) {
|
if (sectionIt == _sections.end()) {
|
||||||
--sectionIt;
|
--sectionIt;
|
||||||
}
|
}
|
||||||
auto item = foundItemInSection(
|
auto item = foundItemInSection(
|
||||||
sectionIt->findItemNearId(scrollTopId),
|
sectionIt->findItemNearId(_scrollTopState.item),
|
||||||
*sectionIt);
|
*sectionIt);
|
||||||
auto newVisibleTop = item.geometry.y() + scrollTopShift;
|
auto newVisibleTop = item.geometry.y() + _scrollTopState.shift;
|
||||||
if (_visibleTop != newVisibleTop) {
|
if (_visibleTop != newVisibleTop) {
|
||||||
_scrollToRequests.fire_copy(newVisibleTop);
|
_scrollToRequests.fire_copy(newVisibleTop);
|
||||||
}
|
}
|
||||||
|
_scrollTopState = ScrollTopState();
|
||||||
}
|
}
|
||||||
|
|
||||||
QMargins ListWidget::padding() const {
|
QMargins ListWidget::padding() const {
|
||||||
|
@ -74,6 +74,9 @@ public:
|
|||||||
clearSelected();
|
clearSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveState(not_null<Memento*> memento);
|
||||||
|
void restoreState(not_null<Memento*> memento);
|
||||||
|
|
||||||
~ListWidget();
|
~ListWidget();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -150,6 +153,10 @@ private:
|
|||||||
Touch,
|
Touch,
|
||||||
Other,
|
Other,
|
||||||
};
|
};
|
||||||
|
struct ScrollTopState {
|
||||||
|
UniversalMsgId item = 0;
|
||||||
|
int shift = 0;
|
||||||
|
};
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
int recountHeight();
|
int recountHeight();
|
||||||
@ -160,6 +167,7 @@ private:
|
|||||||
bool isItemLayout(
|
bool isItemLayout(
|
||||||
not_null<const HistoryItem*> item,
|
not_null<const HistoryItem*> item,
|
||||||
BaseLayout *layout) const;
|
BaseLayout *layout) const;
|
||||||
|
bool isPossiblyMyId(FullMsgId fullId) const;
|
||||||
void repaintItem(const HistoryItem *item);
|
void repaintItem(const HistoryItem *item);
|
||||||
void repaintItem(UniversalMsgId msgId);
|
void repaintItem(UniversalMsgId msgId);
|
||||||
void repaintItem(const BaseLayout *item);
|
void repaintItem(const BaseLayout *item);
|
||||||
@ -229,13 +237,14 @@ private:
|
|||||||
std::vector<Section>::const_iterator findSectionAfterBottom(
|
std::vector<Section>::const_iterator findSectionAfterBottom(
|
||||||
std::vector<Section>::const_iterator from,
|
std::vector<Section>::const_iterator from,
|
||||||
int bottom) const;
|
int bottom) const;
|
||||||
FoundItem findItemByPoint(QPoint point);
|
FoundItem findItemByPoint(QPoint point) const;
|
||||||
base::optional<FoundItem> findItemById(UniversalMsgId universalId);
|
base::optional<FoundItem> findItemById(UniversalMsgId universalId);
|
||||||
base::optional<FoundItem> findItemDetails(BaseLayout *item);
|
base::optional<FoundItem> findItemDetails(BaseLayout *item);
|
||||||
FoundItem foundItemInSection(
|
FoundItem foundItemInSection(
|
||||||
const FoundItem &item,
|
const FoundItem &item,
|
||||||
const Section §ion);
|
const Section §ion) const;
|
||||||
|
|
||||||
|
ScrollTopState countScrollState() const;
|
||||||
void saveScrollState();
|
void saveScrollState();
|
||||||
void restoreScrollState();
|
void restoreScrollState();
|
||||||
|
|
||||||
@ -268,7 +277,8 @@ private:
|
|||||||
Type _type = Type::Photo;
|
Type _type = Type::Photo;
|
||||||
|
|
||||||
static constexpr auto kMinimalIdsLimit = 16;
|
static constexpr auto kMinimalIdsLimit = 16;
|
||||||
UniversalMsgId _universalAroundId = (ServerMaxMsgId - 1);
|
static constexpr auto kDefaultAroundId = (ServerMaxMsgId - 1);
|
||||||
|
UniversalMsgId _universalAroundId = kDefaultAroundId;
|
||||||
int _idsLimit = kMinimalIdsLimit;
|
int _idsLimit = kMinimalIdsLimit;
|
||||||
SharedMediaMergedSlice _slice;
|
SharedMediaMergedSlice _slice;
|
||||||
|
|
||||||
@ -277,8 +287,7 @@ private:
|
|||||||
|
|
||||||
int _visibleTop = 0;
|
int _visibleTop = 0;
|
||||||
int _visibleBottom = 0;
|
int _visibleBottom = 0;
|
||||||
UniversalMsgId _scrollTopId = 0;
|
ScrollTopState _scrollTopState;
|
||||||
int _scrollTopShift = 0;
|
|
||||||
rpl::event_stream<int> _scrollToRequests;
|
rpl::event_stream<int> _scrollToRequests;
|
||||||
|
|
||||||
MouseAction _mouseAction = MouseAction::None;
|
MouseAction _mouseAction = MouseAction::None;
|
||||||
|
@ -104,7 +104,6 @@ void Widget::saveState(not_null<Memento*> memento) {
|
|||||||
|
|
||||||
void Widget::restoreState(not_null<Memento*> memento) {
|
void Widget::restoreState(not_null<Memento*> memento) {
|
||||||
_inner->restoreState(memento);
|
_inner->restoreState(memento);
|
||||||
scrollTopRestore(memento->scrollTop());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Media
|
} // namespace Media
|
||||||
|
@ -52,8 +52,37 @@ public:
|
|||||||
return _type;
|
return _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAroundId(FullMsgId aroundId) {
|
||||||
|
_aroundId = aroundId;
|
||||||
|
}
|
||||||
|
FullMsgId aroundId() const {
|
||||||
|
return _aroundId;
|
||||||
|
}
|
||||||
|
void setIdsLimit(int limit) {
|
||||||
|
_idsLimit = limit;
|
||||||
|
}
|
||||||
|
int idsLimit() const {
|
||||||
|
return _idsLimit;
|
||||||
|
}
|
||||||
|
void setScrollTopItem(FullMsgId item) {
|
||||||
|
_scrollTopItem = item;
|
||||||
|
}
|
||||||
|
FullMsgId scrollTopItem() const {
|
||||||
|
return _scrollTopItem;
|
||||||
|
}
|
||||||
|
void setScrollTopShift(int shift) {
|
||||||
|
_scrollTopShift = shift;
|
||||||
|
}
|
||||||
|
int scrollTopShift() const {
|
||||||
|
return _scrollTopShift;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type _type = Type::Photo;
|
Type _type = Type::Photo;
|
||||||
|
FullMsgId _aroundId;
|
||||||
|
int _idsLimit = 0;
|
||||||
|
FullMsgId _scrollTopItem;
|
||||||
|
int _scrollTopShift = 0;;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user